2012-03-19 7 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 –

答えて

19

あなたが異なる(非メイン)スレッド(S)にはQWidget(またはいくつかの他の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オブジェクトを作成する:GUI部品を保持しています

    .. 
        // 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 this-> moveToThread(はQApplication ::インスタンス() - >スレッド()); \t \t QCoreApplication :: postEvent(これ、新しいQEvent(QEvent :: User)); \t \t} 仮想BOOLイベント(QEvent * EV) {IF(EV->型()== QEvent ::ユーザ) {新しいmygui = W。 w-> show(); がtrueを返します。 } falseを返します。 } }; – jamk

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にそれを接続する:あなたは、各ウィンドウのメッセージを表示したい場合は、あなたがこのようなクラスを持つことができます

以下のようなものとメカニズム:showMessageBox機能は、あなたがそれを行うために必要なものを行い

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

+0

更新された質問 – chacham15

+0

小さな例で更新された回答:) – spbots

+0

待ち時間がありました。私はあなたの答えをテストしていました。 – chacham15

0

上記回答だけでなく、実行されるメインGUIスレッドに任意のアクションを転送するQActionオブジェクト(またはカスタム・クラス・オブジェクト)と組み合わせることができますウィジェットを作成したり、メッセージボックスを表示することができます。 (例えば、sendAction(QAction*)を発行することによって、またはQAction*を具現化するカスタムクラスを実装することによって)。

関連する問題