Возникли проблемы с использованием QThread для настройки графики отдельно от основного потока пользовательского интерфейса.

Я знаю, что есть много вещей, которые могут пойти не так с многопоточностью, и, похоже, это происходит со мной здесь.

Я немного сбит с толку, потому что я использую сигналы и слоты, которые предположительно являются потокобезопасными, но все же получаю ошибки, подобные тем, которые я вижу у других людей в Интернете, которые не используют сигналы и слоты.

Вот моя ситуация:

  1. Из моего основного потока пользовательского интерфейса я создаю новый поток и перемещаю в него объект
  2. Запускается второй поток, и объект обрабатывает некоторые данные.
  3. Когда обработка завершена, объект отправляет сигнал setScene, который я создал, обратно в поток пользовательского интерфейса, попадая в слот.
  4. Слот делает: QGraphicsScene *scene = new QGraphicsScene(sceneIncoming);
  5. Затем он делает: `ui->graphicsView.setScene(scene);

Это по-прежнему говорит мне, что я не могу создать дочерний элемент из родителя в другом потоке. Я не понимаю, как обновить GraphicsView в основном потоке данными сцены из второго потока, несмотря на то, что я использую сигналы и слоты.

Изменить: добавлены фрагменты кода

конструктор mainwindow.cpp

...
...
QThread *thread = new QThread();
GraphicsWorker *worker = new GraphicsWorker();
this->worker = worker;


this->worker->moveToThread(thread);
thread->start();

QObject::connect(this, &MainWindow::beginGraphicsWorker, this->worker, &GraphicsWorker::run);
QObject::connect(worker, &GraphicsWorker::setScene, this, &MainWindow::setScene);
...
....

Запуск GraphicsWorker.cpp()

...processing
...processing
...processing
painter->fillPath(*path, Qt::blue);

scene->addPath(*path);



emit setScene(scene);

Слот setScene mainwindow.cpp

void MainWindow::setScene(QGraphicsScene *sceneIncoming)
{
    QGraphicsScene *scene = new QGraphicsScene(sceneIncoming);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
}

Приведенные выше фрагменты размещены в порядке работы. Итак, еще раз, я хочу передать некоторую обработку, включающую QPainterPath и QGraphicsScene, которая интенсивна и блокирует графический интерфейс, а затем передать данные обратно в основной поток после завершения обработки и позволить основному потоку обновить виджет graphicsView данными сцены. из потока обработки. Я полагал, что копирование sceneIncoming в новый объект позволит новому объекту принадлежать основному потоку, но при этом иметь данные сцены из потока обработки, но, похоже, это не так просто работает.

Возможно, вместо emit setScene(scene) мне нужна сцена.moveToThread(mainThread)?? В таком случае, я думаю, мне нужно передать ссылку на основной поток в обработчик графики.

РЕДАКТИРОВАНИЕ 2: РЕШЕНО На самом деле мне нужны были обе эти строки кода:

scene.moveToThread(this->mainThread);
emit setScene(scene);

Я также добавил перегруженный конструктор, передающий ссылку на основной поток.

Теперь все работает гладко. Я все еще открыт для предложений о том, как лучше сделать это или если это все еще неправильный путь. Дайте мне знать!


person krb686    schedule 08.07.2013    source источник
comment
Здесь так много возможных проблем, но если вы добавите пример кода, а не описание, мы сможем помочь вам намного быстрее. Также обратите внимание, что вы не можете делать ничего, связанного с пользовательским интерфейсом, в любом другом потоке, кроме основного.   -  person TheDarkKnight    schedule 08.07.2013
comment
я не уверен, но QObject::connect() захочет char* из макроса SIGNAL() и SLOT()   -  person Zaiborg    schedule 08.07.2013
comment
@Зайборг Что? У меня вообще не было проблем с подключением сигнала/слота. Эта часть правильная.   -  person krb686    schedule 08.07.2013


Ответы (2)


В связи с тем, что вы запрашиваете лучший способ сделать это, я бы посоветовал вам оставить объект QPainter в основном потоке. Затем пусть второй поток обрабатывает данные и выдает сигналы основному потоку для передачи обработанных им данных, где данные затем добавляются к объекту QPainter в основном потоке.

person TheDarkKnight    schedule 09.07.2013

Попробуй это

scene->moveToThread(QApplication::instance()->thread());
person June Ko    schedule 15.09.2015
comment
Пожалуйста, отредактируйте с дополнительной информацией. Только для кода и попробуйте эти ответы не рекомендуется, поскольку они не содержат контента для поиска. , и не объясняйте, почему кто-то должен попробовать это. - person Rick Smith; 15.09.2015