30

シンプルなTwitterクライアントを作ってPyQtと(Q)スレッドを練習しています。Qthreadが2つあります。

  1. メイン/GUIスレッド。

  2. Twitterフェッチスレッド-X分ごとにTwitterからデータをフェッチします。

したがって、X分ごとに、私のTwitterスレッドは新しいステータス更新のセット(Pythonリスト)をダウンロードします。このリストをメイン/GUIスレッドに渡して、これらのステータスでウィンドウを更新できるようにします。

シグナル/スロットシステムを使用して、「ステータス」PythonリストをTwitterスレッドからメイン/GUIスレッドに転送する必要があると想定しています。したがって、私の質問は2つあります。

  1. Twitterスレッドからステータスを送信するにはどうすればよいですか?

  2. メイン/GUIスレッドでそれらを受け取るにはどうすればよいですか?

私が知る限り、PyQtはデフォルトでシグナル/スロットを介してのみPyQtオブジェクトを送信できます。どういうわけか、送信できるカスタムシグナルを登録することになっていると思いますが、私が見つけたこれに関するドキュメントは、私のような初心者には非常に不明確です。PyQtの本を注文していますが、もう1週間で届かないので、それまで待ちたくありません。:-)

UbuntuでPyQt4.6-1を使用しています

アップデート:

これは、機能しないコードからの抜粋です。まず、シグナル( "newStatuses"、作成したばかりの名前)をメイン/GUIスレッドの関数self.update_tweet_listに「接続」しようとします。

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses (statuses)"),
                       self.update_tweet_list)

次に、Twitterスレッドで、次のようにします。

self.emit(SIGNAL("newStatuses (statuses)"), statuses)

この行が呼び出されると、次のメッセージが表示されます。

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

qRegisterMetaType()を検索しましたが、Pythonに関連する理解できるものは見つかりませんでした。

4

5 に答える 5

27

これを行うこともできますが、これははるかにpythonicです(そして読みやすいです!)。

# create a signal equivalent to "void someSignal(int, QWidget)"
someSignal = QtCore.pyqtSignal(int, QtGui.QWidget)

# define a slot with the same signature
@QtCore.pyqtSlot(int, QtGui.QWidget)
def someSlot(status, source):
    pass

# connect the signal to the slot
self.someSignal.connect(self.someSlot)
于 2010-04-07T20:15:58.367 に答える
7

私がしばらく前に尋ねたこの質問をチェックしてください。何をする必要があるかを理解するのに役立つコード例があります。

信号の登録についてあなたが言ったことは、私にこのコードを思い起こさせます(前述の質問から):

class ProcessingThread(threading.Thread, QtCore.QObject):
    __pyqtSignals__ = ( "progressUpdated(str)",
                        "resultsReady(str)")

私の例では文字列を渡していますが、で置き換えることができるはずstrですlist

可変オブジェクトを渡すことができないことが判明した場合は、私の例のように結果を処理できます(つまりresults、スレッドに変数を設定し、メインスレッドに準備ができていることを伝え、メインスレッドに「選択」を設定します。それらをアップ」)。

アップデート:

シグナルを発信するときに渡す引数のタイプQObject::connect: Cannot queue arguments of type 'statuses'を定義する必要があるため、メッセージが表示されます。渡したいタイプはではありません。liststatuses

信号を接続すると、次のようになります。

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses(list)"),
                       self.update_tweet_list)

信号を発信すると、次のようになります。

self.emit(SIGNAL("newStatuses(list)"), statuses)

それstatusesがリストだとすれば。状況によっては、リストの深いコピーを発行したい場合があることに注意してください。

アップデート2:

わかりlistました、タイプとして使用するのは正しくありません。PyQt4ヘルプリファレンスから:

PyQtシグナルとQtシグナル

Qtシグナルは、C++クラスの一部として静的に定義されます。それらは QtCore.SIGNAL()関数を使用して参照されます。このメソッドは、シグナルの名前とそのC++シグネチャである単一の文字列引数を取ります。例えば::

QtCore.SIGNAL("finished(int)")

戻り値は通常、メソッドに渡されQtCore.QObject.connect() ます。

PyQtを使用すると、新しい信号を動的に定義できます。PyQt信号を放出する行為は、暗黙的にそれを定義します。PyQt v4信号も、このQtCore.SIGNAL() 関数を使用して参照されます。

シグナルPyQt_PyObject引数タイプ

PyQt_PyObjectシグニチャの引数のタイプとして指定することにより、Pythonオブジェクトをシグナル引数として渡すことができます。例えば::

QtCore.SIGNAL("finished(PyQt_PyObject)")

これは通常、リストや辞書などのオブジェクトをシグナル引数として渡すために使用されますが、任意のPythonタイプに使用できます。たとえば、整数を渡すときの利点は、PythonオブジェクトからC ++整数への通常の変換、およびその逆の変換が不要なことです。

渡されるオブジェクトの参照カウントは自動的に維持されます。QtCore.QObject.emit()接続がキューに入れられている場合でも、シグナルのエミッターは、への呼び出し後にオブジェクトへの参照を保持する必要はありません。

于 2010-04-06T16:27:20.853 に答える
7

この例から:

http://doc.qt.digia.com/4.5/qmetatype.html

 int id = QMetaType.type("MyClass");

Pythonで書き留めることができます

from PyQt4 import QtCore    
id = QtCore.QMetaType.type('MyClass')

編集

コメントから抽出された答え:

self.emit(SIGNAL("newStatuses(PyQt_PyObject)"), statuses)
于 2010-04-06T18:30:02.903 に答える
7

PyQtでこれらの古いスタイルのシグナル/スロットを使用している場合、実際にはタイプを宣言する必要はまったくありません。これらは機能するはずです:

QtCore.QObject.connect(self.twit_in,
                   QtCore.SIGNAL("newStatuses"),
                   self.update_tweet_list)

...

self.emit(SIGNAL("newStatuses"), statuses)

この場合、PyQtは、信号を発信するときに、その場で新しい信号タイプを作成します。新しいスタイルのシグナルを使用したい場合は、次のようになります。

class TwitterThread(QThread):
    newStatuses = pyqtSignal(object)

....

self.newStatuses.emit(statuses)
于 2011-03-03T21:31:49.650 に答える
3

(Py)Qtシグナルとスロットは、シングルスレッドの場合とまったく同じようにクロススレッドで機能します。したがって、設定するのに特別なことは何もありません。

メインスレッドにスロット(メソッド)を定義し、スレッドの信号をこのスロットに接続します(接続はメインスレッドでも行われます)。次に、スレッドで、必要に応じて、シグナルを送信するだけで機能するはずです。これは、PyQtでスレッドを使用してシグナルとスロットを使用するためのチュートリアルです。

アプリケーションに移動する前に、まず小さなおもちゃの例で試してみることをお勧めします。

于 2010-04-06T14:28:06.817 に答える