2015-05-06 3 views
0

Мне нужно написать приложение, которое отображает загруженное видео в одном виджете, вытягивает кадры, преобразует их и помещает их в другой виджет, желательно QGraphicsView и, надеюсь, синхронизируется. Для них очень важно синхронизировать их.Qt C++ - преобразование многопоточного видеофрагмента

Я написал тестовую нить, а главное мясо это:

void HSV::display() { 
Ui::MainWindow ui; //1 
int j=0; 
QTimer *timer = new QTimer; 
for(int i=1; i<4; i++){ 
    QString numer = QString::number(i); 
    QImage imageTest(numer+".jpg"); 
    QGraphicsPixmapItem* test = new QGraphicsPixmapItem(QPixmap::fromImage(imageTest)); 
    QGraphicsScene* sceneHSV = new QGraphicsScene; 
    sceneHSV->addItem(test); 
    //2 
    ui.graphicsViewKalibracjaHSV->setScene(sceneHSV); 
    ui.graphicsViewKalibracjaHSV->fitInView(sceneHSV->sceneRect(),Qt::KeepAspectRatio); 
    ui.graphicsViewKalibracjaHSV->show(); 
    timer->start(500); 
    if(i==3) { 
     i=1; 
    } 
    j++; 
    if (j>40) { 
     break; 
    } 
    } 
} 

это не то, что мне нужно, но это просто тест. Если я помещаю текст там, он проходит отлично, продолжает отображать. Но эти образы ... сразу же происходят сбой при достижении первой линии ui (// 2). Я не сомневаюсь, что этот способ делать все очень плохо.

Если я удалю Ui::MainWindow ui; в // 1, он сообщает мне, что ui is not declared in this scope.

Итак, мой вопрос в том, как я могу получить доступ и изменить элементы ui в Mainwindow из отдельного потока?

Редактировать: Хорошо, более практичная идея. Я собираюсь просто передать URL-адрес видеофайла из потока графического интерфейса в рабочий поток, выполнить все операции и передать 2 обработанных изображения назад (для каждого видеокадра), по одному для каждого QGraphicsView. Один нормальный, с отмеченными точками и один преобразованный. Теперь я знаю, как передавать вещи из рабочего потока в поток графического интерфейса, но как передать QString из графического интерфейса в рабочий поток и как его получить?

+0

Я не вижу ** ui-> setupUi (это); ** – Greenflow

ответ

1

Короткий ответ: вы не можете.

Qt Help: Основы многопоточности:

GUI Thread и рабочий поток

Как уже упоминалось, каждая программа имеет одну нить, когда она началась. Этот поток называется «основной нитью» (также известной как «поток GUI» в Qt-приложениях). В этом потоке должен работать GUI GUI. Все виджеты и несколько связанных классов, например QPixmap, не работают во вторичных потоках. Вторичную резьбу обычно называют «рабочий поток », потому что она используется для обработки обработки разгрузки из основного потока .

Что вы можете сделать: вы можете работать с пользовательским интерфейсом в основном потоке, проходят QImage (или другие данные, не связанные с пользовательским интерфейсом) в отдельный поток через сигнал/слот системы, процесс его там и передать его обратно.

UPDATE (? , как я могу это сделать, я имею в виду, передать QImage назад и вперед между потоками и отображать оба видео одновременно и непрерывно - Petersaber)

Я не видео эксперт, но Я могу дать вам намек. Предположим, у вас есть Widget, который принимает QImage и должен его показать. Processor - это объект, который обрабатывает изображение и возвращает его обратно в поток gui. Processor должно быть получено от QObject.

Widget.h

class Widget : public QWidget, private Ui::Widget 
{ 
    Q_OBJECT 
public: 
    explicit Widget(QWidget *parent = 0); 
    void enqueueImage(const QImage &img); 

signals: 
    void process(const QImage &img); 

private: 
    void showNextImage(); 

private slots: 
    void onProcessed(const QImage &img); 

private: 
    QThread *mThread; 
    QScopedPointer <Processor> mProcessor; 
    QList <QImage> mImagesPool; 
}; 

Widget.каст

Widget::Widget(QWidget *parent) : 
    QWidget(parent) 
    , mThread(new QThread(this)) 
    , mProcessor(new Processor) 
{ 
    setupUi(this); 
    mProcessor->moveToThread(mThread); 
    connect(this, SIGNAL(process(QImage)), mProcessor, SLOT(process(QImage))); 
    connect(mProcessor, SIGNAL(processed(QImage)), SLOT(onProcessed(QImage))); 
} 

void Widget::enqueueImage(const QImage &img) 
{ 
    mImagesPool.append(img); 
    showNextImage(); 
} 

void Widget::showNextImage() 
{ 
    if (mImagesPool.isEmpty()) 
     return; 
    emit process(mImagesPool.first()); 
} 

void Widget::onProcessed(const QImage &img) 
{ 
    if (mImagesPool.isEmpty()) 
     return; 
    rawImage->setPixmap(QPixmap::fromImage(mImagesPool.takeFirst())); 
    processedImage->setPixmap(QPixmap::fromImage(img)); 
    showNextImage(); 
} 

Processor.cpp

void Processor::process(const QImage &img) 
{ 
    QImage newImg = img; 
    // Do stuff 
    emit processed(newImg); 
} 
+0

Это «как я могу получить доступ и изменять элементы пользовательского интерфейса в MainWindow из отдельного потока? ". Так почему ты говоришь, что не может? ;-) – Greenflow

+0

Нет, так вы можете обрабатывать данные в отдельном потоке. Вы не можете ** на самом деле ** получать доступ и изменять элементы ui из другого потока, вы должны сделать все это в основном. Может быть, я немного строг :) – Amartel

+0

Gui должен работать в основном потоке. Но это не имеет ничего общего с изменением или доступом к элементам ui. Это тоже данные. Доступ к ним возможен так же, как к любой функции/данным, доступ к которой можно получить через границы потоков. – Greenflow

Смежные вопросы