2013年6月26日水曜日

PyQtの勉強をしてみる。その2 Signal/Slot の使い方

PyQtを始めてSignal/Slotの使い方がいまいち分かっていなかったのでここにまとめておく。
まとめると言ってもリファレンスガイドを参考に頭の整理をするだけなので
原文が良い人はそっちをみたほうが良いかも。
今回説明するのはPyQt4 v4.5で導入されたものだ。 


現状の理解では、シグナル/スロットのはたらきは、

  • オブジェクトをシグナルとスロットを連結させておけば、あるオブジェクトがシグナルを出したときにスロットがそれを感知して動作をする
という感じである。ここにもそんな感じで書いてある。


シグナルを定義するにはPyQt4.Qtcore.pyqtSignal(types[, name])を使う。

シグナルには3つの関数が準備されていて、それぞれ
  • connect:     スロットと繋げる。
  • disconnect: スロットとの繋がりを切る。
  • emit:          シグナルを発信する。


まず基本として、
引数を伴わないシグナルの例は(例そのまま)
from PyQt4.QtCore import QObject, pyqtSignal
class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal()
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit()
    
    def handle_trigger(self):
        #スロット
        print "trigger signal received"
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()


これをちょっとアレンジして、
引数を伴うシグナルの場合は
from PyQt4.QtCore import QObject, pyqtSignal
class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal(int)
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit(15)
    
    def handle_trigger(self, index):
        #スロット
        print "passed integer:", index
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()
    

また、スロットはどんな関数でもconnectできるけど、デコレータ@pyqtSlotでも指定できる。
よくわからんけど、明確にC++のQtスロットとして扱いたいときに使うらしい。
実行速度はデコレータを使ったほうが速くなる。
connectのやり方とかはさっきと一緒。
from PyQt4.QtCore import QObject, pyqtSignal, pyqtSlot

class Hoge(QObject):
    def __init__(self): 
        QObject.__init__(self)
    
    #trigger と名付けたシグナルを定義する。    
    trigger = pyqtSignal(int)
    
    def connect_and_emit_trigger(self):
        #triggerをスロットと繋げる
        self.trigger.connect(self.handle_trigger)
        #スロットにシグナルを送信する。
        self.trigger.emit(15)
    
    @pyqtSlot(int)    
    def handle_trigger(self, index):
        #スロット
        print "passed integer:", index
        
if __name__ == "__main__":
    hoge = Hoge()
    hoge.connect_and_emit_trigger()




0 件のコメント:

コメントを投稿