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