2012-03-19 154 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類。)

相關問題