0

我知道多线程有很多事情会出错,这似乎发生在我身上。

不过我有点困惑,因为我使用的信号和插槽被认为是线程安全的,但仍然遇到类似于我在网络上看到的其他人没有使用信号和插槽的错误。

这是我的情况:

  1. 从我的主 ui 线程,我创建一个新线程并将一个对象移动到它
  2. 第二个线程启动,对象处理一些数据。
  3. 处理完成后,对象将setScene我创建的信号发送回 ui 线程,并降落在插槽中。
  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);

mainwindow.cpp setScene 插槽

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

以上片段按操作顺序发布。再次,我想交出一些涉及密集型 QPainterPath 和 QGraphicsScene 并阻塞 GUI 的处理,然后在处理完成后将数据传回主线程,并让主线程使用场景数据更新 graphicsView 小部件从处理线程。我认为将其复制sceneIncoming到一个新对象中会让新对象在主线程中拥有,但从处理线程中获得场景数据,但它似乎并不那么容易工作。

也许不是emit setScene(scene),我需要 scene.moveToThread(mainThread)?? 在那种情况下,我想我需要将对主线程的引用传递给图形工作者。

编辑2:已解决 实际上我需要这两行代码:

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

我还添加了一个在主线程引用中传递的重载构造函数。

现在一切都很顺利。我仍然愿意接受有关如何更好地做到这一点的建议,或者这仍然是错误的方式。让我知道!

4

2 回答 2

0

关于您要求更好的方法来执行此操作,我建议您将 QPainter 对象留在主线程中。然后,让第二个线程处理数据并向主线程发出信号以传递它已处理的数据,然后将数据添加到主线程上的 QPainter 对象。

于 2013-07-09T08:52:51.513 回答
0

尝试这个

scene->moveToThread(QApplication::instance()->thread());
于 2015-09-15T08:43:16.577 回答