在我的应用程序中,我有一个
QWidget MyWidget
,我需要在单击按钮后构造它。现在,MyWidget 是一个带有许多子组件的重型小部件,而这些子组件也有许多组件。现在,当我尝试在按下按钮后构建小部件时,有时需要等待小部件才会出现,这是我不喜欢的。因此,我需要在单击 PushButton 之前构建小部件并准备好一个实例。 Thread 似乎非常适合这项工作。但我对 Qt Thread 知之甚少。
现在有人可以建议我如何解决这个问题以及可以采取什么措施来解决这个问题吗?
注意: 要明确地说为什么我的小部件这么重,在 MyWidget 中,我有 7*24 个小部件,每个小部件都有一个堆叠的小部件,上面堆叠了两个小部件,每个小部件都有一个按钮。
Qt 不支持在非 GUI 线程中创建小部件。原因很简单:小部件构造函数可以自由访问主线程可以随时使用的线程不安全的 API。因此,即使它看起来可行,但如果你这样做的话,它实际上是代码中的一个错误。
一般来说,在重量级小部件类中,并行化非图形、长时间运行的初始化任务。您可以使用
QtConcurrent::run
来实现此目的。当然,为此目的,您需要使您的实现线程安全。
您还必须确保您绝对、积极地不在小部件代码中使用任何阻塞 API。一般情况下没有 GUI 代码,但没有具体的小部件构造函数,应该永远:
等待任何文件访问完成,
等待任何网络完成,
等待任何数据库访问完成,
使用Qt中的任何
waitForXxxx
方法,使用可能间接访问文件系统的东西,例如
QSettings
。首先,Qt 和几乎所有其他处理 UI 元素的框架(最后是我知道的框架)对于多线程支持都有非常具体的要求。
Qt 需要将每个
QObject
后代(如 QWidget
)分配给一个线程(参见 QObject::thread()
)。
此属性在对象创建时自动分配给正在创建对象的线程。
这样做的问题是,Qt 还要求小部件仅当它属于运行事件循环的同一线程时才接收事件(并且它已正确添加到父小部件)。
如果您在某个不同的线程创建巨大的小部件,它不会接收事件,直到它通过事件循环移动到线程并重新设置父级。
您可以通过调用
QWidget
方法将
QObject::moveToThread()
移动到另一个线程。假设 mParent
是您的 QMainWindow
,而 mMyWidget
是您的巨大小部件:
mMyWidget->setParent(0);
mMyWidget->moveToThread(mParent->thread());
mMyWidget->setParent(mParent); // change this to match your layout requirements.
QWidget::setParent()
了解更多信息。
大型小部件的创建不应在与主线程相同的线程中执行。这留作练习,因为它非常简单,而且 Qt 文档在线程方面非常广泛。
如果在小部件创建完成之前按下按钮,请小心:您必须同步对变量的访问以避免未定义的行为。
这是对问题的一个非常高层次的审视,但只是一个开始,由于您没有提供任何代码,所以我给您一个最低限度的代码;D
另一种选择(可能是更好的选择)是看看为什么你的小部件创建起来如此耗时,但如果没有更多信息,我无能为力。