在Qt中从多个线程中绘图
Drawing from multiple threads in Qt
我正在用Qt写一个程序,它运行10个工作线程,计算空间中物体的轨迹。还需要画出物体的路径。我有一个"体"类派生QGraphicsEllipseItem,它有一个QPainterPath在它。"模拟"类获取世界中的障碍物列表,以及要模拟的身体,并运行直到身体与某些东西碰撞。模拟运行在一个单独的线程中(通过moveToThread完成,而不是通过子类化QThread)。当身体碰撞时,模拟会发出一个信号说它结束了。当所有线程都完成后,我想绘制路径(我通过调用"Body"中的方法来实现路径绘制,该方法在其draw方法中)。
不幸的是,我得到ASSERT错误:
ASSERT: "!unindexedItems.contains(item)" in file graphicsviewqgraphicsscenebsptreeindex.cpp, line 364
它们似乎是随机发生的。我尝试了不同的连接类型,但没有结果。
我正在启动一个循环中的线程。
我正在使用Qt 5.0
一般来说,Qt不能在GUI线程(即执行QApplication::exec()的线程,通常是main()线程)之外做任何GUI操作。
因此,如果您有多个线程操作QGraphicsItems(特别是当前属于QGraphicsScene的QGraphicsItems),那么很可能导致断言失败。也就是说,当Qt GUI线程进行窗口刷新时,它正在从各种QGraphicsItem对象中读取数据,作为其计算的一部分,并且它期望QGraphicsItem在刷新操作期间保持不变。如果在执行刷新例程时(由另一个线程)更改了QGraphicsItem,则主线程进行的计算可能会出错/损坏,并且偶尔会导致断言失败(和/或其他不想要的行为)。
如果你真的需要使用多个线程,你可能需要做的是让线程在自己的私有数据结构上完成所有的计算,Qt GUI线程无法访问这些数据结构。然后,当线程计算出结果时,它们应该将结果发送回Qt GUI线程(通过排队连接或QApplication::postEvent())。然后,GUI线程可以查看结果并使用它们来更新QGraphicsItems等;这将是"安全的",因为此更新不会发生在窗口更新的中间。
如果这听起来工作量太大,那么您可能会考虑在GUI线程中完成所有工作;这样做会更容易、更简单。
正如Jeremy所提到的,Qt渲染必须在主线程上完成。
虽然您可以将其全部移动到主线程,但您可能会选择创建单独的线程以提高效率,特别是因为碰撞检测可能是处理器密集型的。处理这个问题的最好方法是将对象的建模及其物理属性从渲染中分离出来,就像你在模型/视图/控制器模式中所做的那样。
创建不从任何QGraphicsItem/Objects派生的主体实例的表示。然后,它们可以在单独的线程上进行计算,并向主线程中运行的图形对象发送信号,主线程更新每个主体实例的图形表示,从而允许实时渲染轨迹。
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 如何解决多线程绘图的问题不流畅
- GDI+多线程绘图
- 多线程:字符移动、绘图和套接字处理
- 在Qt中从多个线程中绘图
- 在Visual Studio c++中使用Windows窗体进行线程绘图