4

処理用のスレッドと可変量のウィンドウ インスタンスの両方を必要とするクライアント アプリケーションを QT で作成しようとしています。しかし、処理スレッドの 1 つの中に新しいウィンドウを作成する方法を見つけようとして苦労しています。すべての ui 要素を QApplication クラスと同じスレッドで作成する必要があることは理解していますが、インスタンス化できる必要があるか、少なくとも別のスレッドで QDialog への参照が必要です。
スレッドと QDialog の間の通信はシグナルを使用して行うことができます。これについては心配していませんが、実際にウィンドウを作成することは別の問題です。シグナルを使用して、ウィンドウへのインスタンスを作成するようメイン スレッドに指示し、そのインスタンスへのポインターを何らかの方法で取得することもできますが、それは少し複雑で見苦しく思えます。そのようなタスクを達成するためのより良い方法はありますか? メインスレッドの外でQDialogを作成するには、QApplicationクラスが存在していましたか?

編集: Q_INVOKABLE メソッドを試しましたが、複数のスレッドで機能しません。指定したタイプの QDialog を作成し、それへのポインタを返すビュー ファクトリ クラスを作成しました。このクラスはメイン GUI スレッドでインスタンス化され、このクラスへの参照がすべてのワーカー スレッドに送信されます。問題は、スレッドが Qt::BlockingQueuedConnection を使用してファクトリから create メソッドを呼び出すと、invoke メソッドが失敗することです。Qt::DirectConnection に変更すると、invoke メソッドは正しい create メソッドを呼び出しますが、現在のスレッドではワーカー スレッドとして呼び出されます。

私の主な機能は次のようになります:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ViewFactory vFactory;

    vFactory.registerCreator(Util::W_CONNECT, new ConnectWindow::ConnectCreator());

    ClientApp app;

    if(!app.Initialize(&vFactory))
        return 0;

    app.start();
    a.exec();
    .............................

}

そして、ClientApp スレッドからの実行関数は次のようになります。

void ClientApp::run()
{
    QDialog * tmp = NULL;
    QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
                        Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}

私が言ったように、接続タイプを Qt::DirectConnection に変更しても、invokeMothod は失敗しないため、params は問題ではなく、別のワーカー スレッドでメソッドを呼び出します。

4

3 に答える 3

4

GUIスレッドではGuiのことしかできません。明らかな解決策は、ワーカー スレッドが GUI スレッドにメッセージを送信することです = Qt 用語で言えばシグナルです。

ワーカー スレッドが質問する必要がある場合は、GUI スレッドにメッセージを送信し、シグナルが返されるまでブロックする必要があります。

于 2011-02-26T17:52:20.283 に答える
3

AFAIK、シグナル(または を使用して動的に呼び出し可能なメソッドQ_INVOKABLE)またはイベントが道です。

QMetaObject::invokeMethod()(with Qt::BlockedConnection) を使用すると、スレッド間で安全に関数を呼び出し、あまりコーディングしなくても戻り値を取得できることに注意してください。

于 2011-02-26T17:55:28.303 に答える
2

QObject::moveToThreadこの問題を解決できるようです。この関数は、イベント処理ループを別のスレッドに移動します。

Qt ドキュメントの例:

myObject->moveToThread(QApplication::instance()->thread());
于 2012-06-30T19:26:53.763 に答える