10

現在、Python asyncore と pyqt4 を使用してネットワークを学習しようとしています。

私は小さなサーバーをコーディングしました。このサーバーは基本的にポートをリッスンし、受信したすべてのメッセージを送信者に再送信します。

qtsQApplication.exec_()asyncore.loop()は両方とも返されない関数であるため、1 つのスレッドで両方を開始できなかったので、別asyncore.loop()のデーモン スレッドを見つめました。

サーバー クラス ( から派生asyncore.dispatcher) が接続を確立または切断するか、メッセージを送受信するときはいつでも、ウィンドウ クラス ( から派生QtGui.QMainWindow) のメソッドを呼び出し、情報をQPlainTextEdit.

ただし、マウスでテキストをマークしない限り、テキストは表示されません。

Python コンソールに次のエラー メッセージが表示されます。

QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)

これは別のスレッドからqt関数を呼び出すことによって引き起こされる可能性があり、プレーンな関数呼び出しの代わりにシグナルとスロットを使用すると問題が解決する可能性があることをいくつかのフォーラムで読みましたが、シグナルも試しましたが、まだこのエラーが発生します。

それで、(それが本当に私の問題の原因である場合)別のスレッドからqtオブジェクトのメソッドを呼び出す正しい方法は何ですか?

詳細情報を編集: asyncore.loop() 呼び出しは子スレッドにあり、実際にはブロックされていませんが、asyncore.loop() の実行時のみ、サーバー クラス (asyncore.dispatcher) がネットワークを実行できます。したがって、asyncore.loop() の実行時に、サーバー クラスのメソッドが asyncore.loop() (= 子スレッド) によって呼び出され、これらの中で、メイン スレッドで実行されているウィンドウ クラスにシグナルを送信しようとしました。

EDIT:私は今それが働いているようです、私は私のコードにいくつかのエラーがありました.

編集:小さな例: http://paste2.org/p/635612 (リンク切れ)

4

1 に答える 1

14

メインスレッド以外のスレッドから QtGui クラスにアクセスしようとしているようです。他の GUI ツールキット (Java Swing など) と同様に、これは許可されていません。Threads and QObjects Web ページから:

QObject は再入可能ですが、GUI クラス、特に QWidget とそのすべてのサブクラスは再入可能ではありません。メインスレッドからのみ使用できます。

解決策は、メイン スレッド (GUI オブジェクトが存在する場所) とセカンダリ スレッド間の通信にシグナルとスロットを使用することです。基本的に、一方のスレッドでシグナルを発行し、もう一方のスレッドを介して QObjects に配信されます。上でリンクしたページには、これについての良い議論があります。実際、 Qt でのスレッドのサポートに関するセクション全体を読むとよいでしょう。

発生する可能性のある問題の 1 つは、通常、完全なシグナルとスロットのサポートをスレッド全体で機能させるには、(または PyQt と同等のものを使用して) 子スレッドでイベント ループを開始し、QThread::exec()シグナルをスロットに配信できるようにする必要があることです。そこに住むQObjects。あなたの場合、 へのブロッキング呼び出しを行っているように聞こえます。これによりasyncore.loop()、これを行うことができなくなります。ただし、一方向 (子スレッドからメイン スレッドのウィジェット) にのみシグナルを送信する必要がある場合は、問題はないと思います。

于 2010-01-20T21:09:55.310 に答える