我遇到以下问题:我们的主应用程序使用Qt工具包来显示窗口和用户交互。然而,我们应用程序的很大一部分对GUI部分一无所知。我现在创建了以下设计:在多线程的Qt应用程序中处理升压信号
- 有一个单例类可请求呈现给定对象(OpenSceneGraph的节点;但这是无关的问题)
- 呈现请求使单以发射信号
- 有一个在主窗口类插槽(其中使用Qt)来处理渲染对象
- 目前,该槽只创建一个新的文本编辑窗口小部件,并将其放置在主窗口的
QMdiArea
但是,当我尝试创建新的小部件时,应用程序不可避免地会崩溃。错误消息区域:
QObject::setParent: Cannot set parent, new parent is in a different thread
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
myApplication: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted
在细读了stackoverflow后,我发现了类似的问题(它不适用于这种情况)。很显然,当我在另一个线程中更改主窗口中的某些内容时,Qt并不喜欢它。但是,我没有自觉创建新的主题,我认为单(这是在主函数QApplication()
呼叫后立即创建)应在同一个线程为Qt的。显然,我错了。
这里是一个小例子,显示我正在做的事情(我已经提取代码的相关部分,这样的例子并不完全功能):
class Object
{
public:
};
class Singleton
{
public:
typedef boost::signals2::signal<void (Object*)> signalShowObject;
signalShowObject _showObject;
};
class MainWindow : public QMainWindow
{
public:
MainWindow()
{
Singleton::getInstance()->_showObject.connect(boost::bind(&MainWindow::showObject, this, _1));
// Set up MDI area etc.
}
private:
QMdiArea* _mdiArea;
void showObject(Object* object)
{
// Creating a new subwindow here causes the crash. The `object` pointer is
// not used and has just been included because it models my real problem
// better.
_mdiArea->addSubWindow(new QTextEdit())->show();
}
};
我试图解决这个问题有一直很笨拙:
- 我在
MainWindow
类创建了一个新的Qt 信号具有相同签名的加速信号 - 在SL OT处理该升压信号,我发射新
Qt
信号,使指针移到 - 我现在创建接收指针新的Qt槽
当我在新的插槽打开一个新的窗口,一切正常。但是,这让我觉得很笨拙。我是否需要级联全部提升这样的信号还是有更好的方法?
只是要清楚。每个gui操作必须在QApplication线程中完成。如果你想检查你的方法是否在正确的线程调用中使用qDebug()<< thread()<< QThread :: currentThread();告诉我们showObject成员中该调试的输出是什么。 –
@KamilKlimek我在我的“真实”应用程序中获得了线程ID,它们确实不同。 – Gnosophilon
你可以调用插槽,然后用QMetaObject :: invokeMethod –