除了主 ui 线程之外,使用 QThread 设置图形时遇到问题

Posted

技术标签:

【中文标题】除了主 ui 线程之外,使用 QThread 设置图形时遇到问题【英文标题】:Having trouble using QThread to setup graphics apart from main ui thread 【发布时间】:2013-07-08 13:53:39 【问题描述】:

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

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

这是我的情况:

    从我的主 ui 线程,我创建了一个新线程并将一个对象移动到它 第二个线程启动,对象处理一些数据。 处理完成后,对象将我创建的setScene 信号发送回 ui 线程,并落在插槽中。 插槽执行:QGraphicsScene *scene = new QGraphicsScene(sceneIncoming); 然后执行:`ui->graphicsView.setScene(scene);

这仍然告诉我不能从另一个线程中的父级创建子级。尽管我使用了信号和插槽,但我不明白如何使用来自第二个线程的场景数据更新主线程中的 graphicsView。

编辑:添加代码 sn-ps

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 run()

...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();

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

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

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

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

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

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

【问题讨论】:

这里有很多可能的问题,但是如果您添加代码示例而不是描述,我们将能够更快地为您提供帮助。另请注意,除了主线程之外,您不能在任何其他线程上执行任何与 UI 相关的操作。 我不是 shure,但 QObject::connect() 需要来自 SIGNAL()SLOT() 宏的 char*s @Zaiborg 什么?我根本没有遇到信号/插槽连接问题。那部分是正确的。 【参考方案1】:

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

【讨论】:

【参考方案2】:

试试这个

scene->moveToThread(QApplication::instance()->thread());

【讨论】:

请编辑更多信息。纯代码和“试试这个”的答案是discouraged,因为它们不包含可搜索的内容,也没有解释为什么有人应该“试试这个”。

以上是关于除了主 ui 线程之外,使用 QThread 设置图形时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 UI 制作一个豆瓣电影信息查看器,初识QThread多线程...

等待QThread时UI会阻塞/如何正确使用QThread

QThread 阻塞主应用程序

我可以在主线程(UI 线程)之外创建 UI 吗?

PyQt:如何从 QThread 获取 UI 数据

我可以在属于主线程的 QThread 中使用 waitForReadyRead 吗?