2015-11-06 104 views
1

我正在Qt 5.5与Qt Creator一起工作。 我有一个名为settingsWindow的大类,正如名称所示,它负责各种设置。然后使用这些设置来启动一些QDialog,这些QDialog在qGraphicsView中的场景中显示非常复杂的动画,并通过QCoreApplication :: processEvents()不断更新,这些动画反过来保持GUI的响应。动画是通过QDialog的start()方法启动的。 我想同时运行这些QDialog,例如通过按钮启动,在同一时刻启动所有这些QDialog。我试过使用一个包装器,也就是从QObject继承的一个简单的类,每次将它分配给不同的线程,但是如果我启动一个QDialog,一切正常,当我开始第二个时,第一个“块”(动画停止并且仅在第二个Qdialog中动画可见)。 我唯一的解决方案是为它们中的每一个启动一个单独的QProcess(这样我确信它们分开运行并且位于不同的线程中),但是我需要重写逻辑(每个QDialog的单独程序)。如何在不同线程中同时运行多个QDialog?

任何更简单的解决方案?先谢谢你。

+0

你如何显示对话框?你叫'QDialog :: exec()'? – jpo38

+0

我调用'QDialog :: show()',然后'name_of_the_dialog-> start()',开始动画。 – Michael

回答

1

它不能在一个进程内完成。任何触及QWidget的东西只能在主线程中运行。你的代码碰巧运行的是巧合,你依赖于未定义的行为,而Qt从来没有这样用过。没有这方面的测试,依此类推:你是独立的,你必须深入挖掘Qt代码来弄清楚改变什么来允许任何这些。

如果你这样做太复杂的GUI线程渲染的动画,你坚持使用传统的小工具,你必须通过他们使用QtConcurrent::runQPainter一个QImage,因为异步工作方式来呈现。异步工作人员然后将图像发送到对话框,然后后者会将它们粘贴到屏幕上。

有关两个相关示例的链接,请参见this answer

否则,请使用QML。对于大多数情况,从CPU的角度来看,QML动画几乎是不可操作的。 GPU执行所有渲染,并且表现令人赞叹。

多处理方法当然也是可行的。随意使用指定用于进程间通信的管道的随机名称的参数来启动相同的可执行文件,并修改行为(第1对第2对话等)。请参阅this answer了解如何轻松启动自己。

+0

你的意思是“你的代码恰好运行在什么意义上是一个巧合”?你是否想要在一个线程中移动一个QDialog? 我想我会继续为每个QDialog提供一个单独的过程。关于QDialog之间的通信,我不需要进程间通信(它们实际上不会返回任何内容,而且它们可以处理来自settingsWindow的完全不同的变量)。 “动画”实际上是一种图形构造,从源节点开始,尝试到达目标节点,向场景添加新的点和线。 QPainter是一种很好的渲染方式吗? – Michael

+0

*你是否想要在一个线程中移动QDialog?*是的。不要这样做。这不应该起作用,它不被支持,如果你有任何问题,你自己完全独立(除非你雇用某人,当然)。 *“动画”实际上是一个图形构造,从源节点开始并尝试到达目标节点*将数据和运行于其上的算法从可视化中分离出来。那是你的问题。渲染速度不太慢,很可能。不过,你的计算正在放慢渲染速度。 –

0

很难提供任何代码。

您可以尝试为每个对话框创建一个线程,然后将一个对话框移动到每个线程(使用QObject::moveToThread)。

每个线程都必须让其他人有机会在一段时间内执行指令(调用QThread::yieldCurrentThreadQThread::sleep)。否则,如果一个线程处于一个巨大的循环中,那么它将永远不会给其他人一个做某事的机会。

+0

是的,事实上,这是一个巨大的循环,导致一个线程阻塞另一个。我认为,由于我有一个多核处理器,每个生成的线程都会自动分配给另一个核心,但似乎并不是这种情况。奇怪的是,无论如何,GUI在每个QDialog中都是响应式的(我在每个QDialog中也有一个简单的记时器,显示自启动以来的时间,并且它可以持续顺畅地运行)。 你如何建议实施停止线程让其他人继续?每个100 ms从一个线程交换到另一个线程的“QTimer”?它不会造成开销吗? – Michael

+0

尝试从线程调用'yieldCurrentThread',这会将控件传递给另一个控件。 – jpo38

+0

如何? 如果我创建了两个QDialogs,那么执行 'QThread * t1 = new QThread; QThread * t2 = new QThread; dialog1-> moveToThread(t1); dialog2-> moveToThread(t2); dialog1-> show(); dialog2-> show(); dialog1-> start(); dialog2-> start();' 我应该使用'QTimer'还是每个'n'睡眠/产生一个线程并继续使用另一个? – Michael