从Qt中的多线程绘图(Drawing from multiple threads in Qt)

2019-09-01 07:19发布

我正在写在Qt的,它运行10个工作线程计算其在空间中的物体的轨迹的程序。 他们也有拉拢的对象的路径。 我有一个“身体”类派生QGraphicsEllipseItem,它有它QPainterPath。 在“模拟”类负责在世界障碍列表,以及身体和模拟运行,直到身体的东西发生碰撞。 在一个单独的线程模拟运行(与moveToThread完成,而不是通过继承的QThread)。 当身体碰撞,模拟发出信号说,它完成了。 当所有线程都完成,我想(通过调用“身体”的方法使路径在其绘制方法绘制我这样做)绘制的路径。

不幸的是,我得到ASSERT错误:

ASSERT: "!unindexedItems.contains(item)" in file graphicsview\qgraphicsscenebsptreeindex.cpp, line 364

他们看似随机发生。 我试过不同的连接类型,都没有结果。
我开始在一个循环的线程。
我使用Qt 5.0

Answer 1:

一般来说,使用Qt你不能做的GUI线程之外的任何GUI操作(即正在执行的QApplication :: EXEC(),它通常是在main()线程的线程)。

所以,如果你有多个线程操作QGraphicsItems(尤其是QGraphicsItems是目前一个QGraphicsScene的一部分),这可能是你的断言失败的原因。 也就是说,当Qt的GUI线程做它的刷新窗口,它读取来自不同的QGraphicsItem对象数据作为其计算的一部分,它预计QGraphicsItems保持不变的刷新操作的持续时间。 如果的QGraphicsItem改变(由另一个线程),同时刷新程序执行,然后由主线程进行的计算可以成为错误/损坏,并且有时会导致一个断言失败(和/或其他有害的行为)。

如果你确实需要使用多个线程,你可能会需要做的是线程做他们对Qt的图形用户界面线程有没有访问自己的私人数据结构中的所有计算。 然后,当线程都计算其结果,就应该将结果发送回Qt的GUI线程(通过排队连接或QApplication的事件后::())。 然后,GUI线程可以看看结果,并利用它们来更新QGraphicsItems等; 这将是“安全的”,因为此更新不能在一个窗口中更新过程中发生的。

如果这听起来像太多的工作,那么你可以考虑只是做在GUI线程的一切; 这将是更容易和简单,使一切工作可靠的方式。



Answer 2:

正如杰里米提到的那样,Qt的渲染必须在主线程上完成。

虽然你可以把它全部移动到主线程,您可能已经选择创建效率独立的人,尤其是碰撞检测可以是处理器密集型的。 处理这种情况最好的办法就是对象及其物理模型从他们的渲染分裂,就像在一个模型/视图/控制器模式。

创建不是从任何的QGraphicsItem /对象得出的身体情况的陈述。 然后,这些可以做单独的线程上进行计算,并有信号,是在主线程,更新每个体实例的图形表示,允许轨迹的实时渲染运行图形对象。



文章来源: Drawing from multiple threads in Qt