2012-03-19 82 views
10

我有一个应用程序,其中每个线程(主线程除外)需要创建它自己的窗口。我尝试创建一个线程,然后在run函数中调用this->exec()。但是,在我接到该呼叫之前,我收到错误:ASSERT failure in QWidget: "Widgets must be created in the GUI thread."如何在不同的QT线程中创建一个窗口?

我想弹出消息窗口。问题是源有多个线程,每个线程可能需要弹出自己的消息。

+2

不要试图从后台/工作线程显示UI。而是从主GUI线程显示该UI。安排您的背景/工作人员发出GUI线程信号,以完成此任务。本示例显示了如何执行此操作:http://doc.qt.nokia.com/4.7-snapshot/thread-basics.html#example-3-clock。 – 2012-03-19 21:48:16

回答

19

如果你需要创建QWidget的(或其他一些GUI组件(S))在不同的(非主)线程(S),你可以在这样的方式实现:

  • 创建简单的包装,其保持GUI部件:

    // gui component holder which will be moved to main thread 
    class gui_launcher : public QObject 
    { 
        QWidget *w; 
        // other components 
        //.. 
    public: 
        virtual bool event(QEvent *ev) 
        { 
        if(ev->type() == QEvent::User) 
        { 
         w = new QWidget; 
         w->show(); 
         return true; 
        } 
        return false; 
        } 
    }; 
    
  • 创建在主线程

  • 另一个线程体QApplication对象:

    .. 
        // create holder 
        gui_launcher gl; 
        // move it to main thread 
        gl.moveToThread(QApplication::instance()->thread()); 
        // send it event which will be posted from main thread 
        QCoreApplication::postEvent(&gl, new QEvent(QEvent::User)); 
    .. 
    
  • 快乐,:)

+2

你好,我做只是为了好玩 \t模板 类gui_launcher一些小的改进:公共QObject的 { mygui *宽; //其它组分 公共: \t空隙add2Gui() \t \t { \t \t这 - > moveToThread(的QApplication ::实例() - >螺纹()); QCoreApplication :: postEvent(this,new QEvent(QEvent :: User)); \t \t} 虚拟BOOL事件(QEvent的* EV) { 如果(EV->类型()== QEvent的::用户) { 瓦特=新mygui; w-> show(); 返回true; } return false; } }; – jamk 2012-12-11 12:44:57

1

我不相信这是可能的。其他非GUI组件可以在其他线程中运行,并且通常通过信号/插槽机制进行通信。

7

Qt将只允许您在GUI线程中创建GUI元素 - 您需要从其他线程显示什么?有关使用非GUI线程中的数据更新进度条的示例,请参阅This answer之类的内容。

更新:

如果你想显示每个窗口的消息,你可以有一个这样的类:

class MyWorkerThread : public QThread 
{ 
    Q_OBJECT 
signals: 
    void sendMessage(QString msg); 
private: 
    void run() 
    { 
    /* do stuff */ 
    emit sendMessage(QString("This thread is doing stuff!")); 
    /* do more stuff */ 
    } 
}; 

然后通过信号插槽将其连接在你的GUI机制类似于:

connect(workerThread, SIGNAL(sendMessage(QString)), 
     guiController, SLOT(showMessageBox(QString))); 

其中showMessageBox函数完成您所需要的功能。

+0

更新后的问题 – chacham15 2012-03-19 21:44:22

+0

用一个小例子更新了答案:) – spbots 2012-03-19 22:35:02

+0

等待,我正在测试你的答案。 – chacham15 2012-03-20 17:51:41

0

上述答案可以与QAction对象(或自定义类对象)被组合以任何动作传递到主界面线程中执行,而不是仅仅创建窗口小部件或显示消息框。 (例如,通过发出sendAction(QAction*),或实现体现QAction*的自定义QEvent类。)

相关问题