シンプルなTwitterクライアントを作成して、PyQtと(Q)スレッドの練習をしています。 2つのQthreadがあります。
メイン/ GUIスレッド。
Twitterフェッチスレッド-X分ごとにTwitterからデータをフェッチします。
X分ごとに、私のTwitterスレッドが新しいステータス更新のセットをダウンロードします(a Pythonリスト)。このリストをメイン/ GUIスレッドに渡して、更新できるようにします。これらのステータスのウィンドウ。
シグナル/スロットシステムを使用して「ステータス」PythonリストをTwitterスレッドからメイン/ GUIスレッドに転送する必要があると想定しているので、私の質問は2つあります。
Twitterスレッドからステータスを送信するにはどうすればよいですか?
メイン/ GUIスレッドでそれらを受け取るにはどうすればよいですか?
私の知る限り、PyQtはデフォルトでPyQtオブジェクトをシグナル/スロット経由でのみ送信できます。どういうわけか私が送信できるカスタム信号を登録することになっていると思いますが、私が見つけたこれに関するドキュメントは私のような初心者には非常に不明瞭です。私はPyQtの本を注文していますが、もう1週間で届かず、それまで待ちたくありません。 :-)
UbuntuでPyQt 4.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に関連するものは理解できませんでした。
この例から:
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)
これを行うこともできますが、これはより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)
これをチェックしてください 私が尋ねた質問 しばらく前に。何をする必要があるかを理解するのに役立つコード例があります。
あなたの信号の登録についてあなたが言ったことは、私にこのコードを思い起こさせます(前述の質問から):
_class ProcessingThread(threading.Thread, QtCore.QObject):
__pyqtSignals__ = ( "progressUpdated(str)",
"resultsReady(str)")
_
私の例では文字列を渡していますが、str
をlist
に置き換えることができるはずです。
変更可能なオブジェクトを渡すことができないことが判明した場合は、この例のように結果を処理できます(つまり、スレッドでresults
変数を設定し、メインスレッドに準備ができていることを通知します。メインスレッドを「ピックアップ」します)。
更新:
シグナルを送信するときに渡す引数のtypeを定義する必要があるため、メッセージ_QObject::connect: Cannot queue arguments of type 'statuses'
_が表示されます。渡すタイプはlist
ではなくstatuses
です。
信号を接続すると、次のようになります。
_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()
の呼び出し後、信号のエミッターがオブジェクトへの参照を保持する必要はありません。
これらの古いスタイルの信号/スロットを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)
(Py)Qtシグナルとスロットは、シングルスレッドと同じようにクロススレッドで機能します。したがって、特別に設定するものはありません。
メインスレッドにスロット(メソッド)を定義し、スレッドのシグナルをこのスロットに接続します(接続はメインスレッドでも行われます)。次に、スレッドで、必要なときにシグナルを発行するだけで動作します。 チュートリアルはこちら PyQtでスレッド化されたシグナルとスロットの使用について。
アプリケーションに移る前に、まず小さなおもちゃの例で試してみることをお勧めします。