PySideの信号とスロット

6241 ワード

本稿では、主にPySideでQtの信号とスロットを使用する方法を紹介し、新式の信号とスロットの書き方(この方式はさらにPythonic)に重点を置き、それ以外にも旧式の信号スロット方式(依然として利用可能であるが、使用を推奨しない)を簡単に紹介する.
新しい信号スロットスタイルはPyQtの4.5バージョンに導入され、PySideはこの処理方式を参考にしており、この方式の詳細な実装ガイドはPSEP 100を参照することができる.
  • 従来の信号およびスロット構文
  • 従来の信号スロット構文ではQtCoreが用いられている.SIGNALとQtCore.SLOTの2つのマクロを実装し、次の例では、この方法をどのように使用するかを示します.
    def someFunc():
        print "someFunc has been called!"
     
    button = QtGui.QPushButton("Call someFunc")
    QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), someFunc)
    例ではQPShButtonが定義されており、クリック信号をsomFuncというスロット関数に接続し、ボタンをクリックするとコンソールからsomeFunc has been calledが出力されます!
  • 新しい信号スロット構文
  • 新しい信号スロット構文の例は次のとおりです.
    def someFunc():
        print "someFunc has been called!"
     
    button = QtGui.QPushButton("Call someFunc")
    button.clicked.connect(someFunc)
    このコードは、上述した従来の信号スロットの効果も同様に実現する.
  • QtCoreを使用する.Signal()カスタム信号
  • 信号はQtCoreのSignalクラスを使用して定義することができ、PythonまたはCタイプをパラメータとして伝達することができ、信号を再ロードする必要がある場合は、タイプパラメータをメタグループまたはリストに置くことができる.
    また、信号パラメータには、名前付きパラメータ方式nameを用いて信号の名前を指定することができ、nameパラメータが入力されなければ、付与された変数名を信号の名前とすることができる.
    次の例では、QtCoreの使用方法を示します.Signalは信号の様々な方法を定義する.
    なお、信号はQObjectのサブクラスにのみ定義され、定義された信号はサブクラスのQMetaObjectに追加される.
  • QtCoreを使用する.Slot()カスタムスロット関数
  • スロット関数はQtCoreを通過する.Slot()の装飾器は定義とリロードを実現し、溝関数を定義するには、1つのタイプのパラメータを入力するだけでいいです.定義信号とは異なり、入力リストやメタグループを使用してスロット関数を再ロードすることはできません.異なるスロット関数を定義するには、新しい装飾器を定義する必要があります.別の違い:Slotは同じように名前付きパラメータnameとresultを入力することができ、resultはこの関数の戻り値タイプを識別することができ、nameはSlotの名前を設定することができ、nameが設定されていない場合、この溝関数の名前は装飾器が装飾した関数の数である.
  • サンプルプログラム
  • 以下に、最も簡単な方法から比較的複雑な方法まで、PySideで信号とスロットを使用する方法を主に示す例示的なプログラムを示します.
  • 例1
  • パラメトリックなしの信号とスロットの使用を実証した.
        #!/usr/bin/env python
         
        import sys
        from PySide import QtCore, QtGui
         
        # define a function that will be used as a slot
        def sayHello():
            print 'Hello world!'
         
        app = QtGui.QApplication(sys.argv)
         
        button = QtGui.QPushButton('Say hello!')
         
        # connect the clicked signal to the sayHello slot
        button.clicked.connect(sayHello)
        button.show()
         
        sys.exit(app.exec_())
    
  • 例2
  • QtCoreを用いるパラメータ付き信号とスロットを実証した.SignalとQtCore.Slotカスタム信号とスロットの作成
        #!/usr/bin/env python
         
        import sys
        from PySide import QtCore
         
        # define a new slot that receives a string and has
        # 'saySomeWords' as its name
        @QtCore.Slot(str)
        def saySomeWords(words):
            print words
         
        class Communicate(QtCore.QObject):
            # create a new signal on the fly and name it 'speak'
            speak = QtCore.Signal(str)
         
        someone = Communicate()
        # connect signal and slot
        someone.speak.connect(saySomeWords)
        # emit 'speak' signal
        someone.speak.emit("Hello everybody!")
    
  • 例3
  • 信号とスロット関数のリロード方法を実証した.
        #!/usr/bin/env python
         
        import sys
        from PySide import QtCore
         
        # define a new slot that receives a C 'int' or a 'str'
        # and has 'saySomething' as its name
        @QtCore.Slot(int)
        @QtCore.Slot(str)
        def saySomething(stuff):
            print stuff
         
        class Communicate(QtCore.QObject):
            # create two new signals on the fly: one will handle
            # int type, the other will handle strings
            speakNumber = QtCore.Signal(int)
            speakWord = QtCore.Signal(str)
         
        someone = Communicate()
        # connect signal and slot properly
        someone.speakNumber.connect(saySomething)
        someone.speakWord.connect(saySomething)
        # emit each 'speak' signal
        someone.speakNumber.emit(10)
        someone.speakWord.emit("Hello everybody!")
    
  • 例4
  • 複数の信号を定義する新しい方法(リストを使用する方法)を実証した.
        #!/usr/bin/env python
         
        import sys
        from PySide import QtCore
         
        # define a new slot that receives an C 'int' or a 'str'
        # and has 'saySomething' as its name
        @QtCore.Slot(int)
        @QtCore.Slot(str)
        def saySomething(stuff):
            print stuff
         
        class Communicate(QtCore.QObject):
            # create two new signals on the fly: one will handle
            # int type, the other will handle strings
            speak = QtCore.Signal((int,), (str,))
         
        someone = Communicate()
        # connect signal and slot. As 'int' is the default
        # we have to specify the str when connecting the
        # second signal
        someone.speak.connect(saySomething)
        someone.speak[str].connect(saySomething)
         
        # emit 'speak' signal with different arguments.
        # we have to specify the str as int is the default
        someone.speak.emit(10)
        someone.speak[str].emit("Hello everybody!")
    
  • 例5
  • 完全な送信信号の方式(送信信号を関数にカプセル化し,外部に関数を呼び出すことができる方式)を実証した.
        #!/usr/bin/env python
         
        import sys
        from PySide import QtCore
         
        class Communicate(QtCore.QObject):    # !!! Must inherit QObject for signals
           
           speak = QtCore.Signal()
         
           def __init__(self):
               # !!! Must init QObject else runtime error: PySide.QtCore.Signal object has no attribute ‘emit’
               super(Communicate, self).__init__()
         
           def speakingMethod():
               self.speak.emit()
         
        someone = Communicate()
        someone.speakingMethod()
    

    信号はクラスインスタンスの動的オブジェクトであり、クラスの属性ではないため、直接クラスを通じて信号とスロット関数を接続することはできません.
    翻訳文章の原文アドレス:Signals and Slots in PySide
  • 備考(非翻訳)
  • 1.PySideでSlotの名前を付ける方法はBugであり、Slotの名前をカスタマイズすることはできません.たとえば、次のようにします.
    @QtCore.Slot(name = "on_pushButton_clicked") 
    def testButton_pressed(self): print "pressed button"
    上記のドキュメントの説明に従ってSlotの名前をon_とするpushButton_clickedですが、使用中はスロット関数に接続できません.具体的には、Named Slot Bug?
    2.本明細書の「新しい信号スロット構文」セクションに示す例に注意してください.someFuncはQtCoreを識別していません.Slot、しかし依然として信号とスロット関数を接続することができて、事実上Pythonの中の任意の関数はすべてスロット関数として使用することができて、Slotと宣言する必要はなくて、それが信号と接続する規則(パラメータに対応する上)に合致する限り、QtCoreを使用します.Slotが表示する宣言は、Pythonの暗黙的な変換タイプを必要とせずに効率を向上させることができます.具体的には参考にしてください:Is the PySide Slot Decorator Necessary?