2017-06-02 17 views
1

Qtでスレッドを正しく使用する方法をよく理解しているので、小さなおもちゃの例を書いています。QObjectが実行中のスレッドに移動し、シグナルが呼び出されますウィンドウがクリックされたときのそのオブジェクトPyQt5を使用して正しいスレッドでシグナルが受信されない

問題は、スロットが決して正しいスレッドで呼び出されないことです。常にメインスレッドで呼び出されます。

これは、次のコードで実装されています。

のようなものを出力
from PyQt5 import QtWidgets, QtCore 

class WidgetWithInput(QtWidgets.QWidget): 

    widgetClicked = QtCore.pyqtSignal() 

    def mousePressEvent(self, event): 
     self.widgetClicked.emit() 

class MyObject(QtCore.QObject): 

    aSignal = QtCore.pyqtSignal() 

    def __init__(self, *args, **kwargs): 
     super(MyObject, self).__init__(*args, **kwargs) 

     self.aSignal.connect(self.onASignal) 

    def onASignal(self): 
     print('MyObject signal thread: %s' 
       % str(int(QtCore.QThread.currentThreadId()))) 


class SimpleDisplay(QtWidgets.QMainWindow): 
    ''' Class presenting the display subsytem 
    ''' 

    def __init__(self, my_object, *args, **kwargs): 

     super(SimpleDisplay, self).__init__(*args, **kwargs) 

     self._my_object = my_object 

     self._widget = WidgetWithInput() 

     self.setCentralWidget(self._widget) 
     self._widget.widgetClicked.connect(self._do_something) 

    def _do_something(self): 
     self._my_object.aSignal.emit() 

def main(run_until_time=None): 

    import sys 
    app = QtWidgets.QApplication(sys.argv) 
    print ('main thread: %s' % str(int(QtCore.QThread.currentThreadId()))) 

    concurrent_object = MyObject() 
    display = SimpleDisplay(concurrent_object) 

    myobject_thread = QtCore.QThread() 
    myobject_thread.start() 

    concurrent_object.moveToThread(myobject_thread) 

    display.show() 

    exit_status = app.exec_() 

    myobject_thread.quit() 
    myobject_thread.wait() 

    sys.exit(exit_status) 

if __name__ == '__main__': 
    main() 

:私はこれらの2つのプリントスレッドIDが異なることが期待される

main thread: 139939383113472 
MyObject signal thread: 139939383113472 

を。

ここに何か不足していますか?キューに入れる信号を明示的に設定しても何も変わりません。

@three_pinapplesのおかげで
+1

はあなたが前に 'MyObject.aSignal'信号*をトリガー*動いているように見えますMyObject'インスタンスを新しいスレッドに追加します。したがって、あなたが見る出力。 –

+0

@ G.M。私は信号がオブジェクトのスレッドで受信されたという理解の元であった。私はこれで間違っていることをうれしく思っていますが、正しいスレッドで信号をどのように接続するかはわかりません。私は 'ThreadChange'イベント(スレッドが変更される前の最後のイベントです)に新しいシグナルを出す、シグナルを接続するハンドラが動作しない(同じ前と同じ結果)。私はそれを 'main'関数で明示的に行うことで動作させることができますが、これは私の' main'が知識をクラスIMOに制限する必要があります。 –

+0

これに加えて、スレッドを 'MyObject'に渡して問題を解決し、' __init__'で 'self.moveToThread'を使用することができます。これは、MyObjectに知識があることを私に要求するので、少し幸運なようです。 –

答えて

0

は、コメント欄で彼の提案は、問題を解決:スロットはQtCore.pyqtSlotで飾らする必要があります

class MyObject(QtCore.QObject): 

    aSignal = QtCore.pyqtSignal() 

    def __init__(self, *args, **kwargs): 
     super(MyObject, self).__init__(*args, **kwargs) 

     self.aSignal.connect(self.onASignal) 

    @QtCore.pyqtSlot() 
    def onASignal(self): 
     print('MyObject signal thread:\t %s' 
       % str(int(QtCore.QThread.currentThreadId()))) 
関連する問題