PySide——Python圖形化界面入門教程(四)
——創建自己的信號槽
——Creating Your Own Signals and Slots
翻譯自:http://pythoncentral.io/pysidepyqt-tutorial-creating-your-own-signals-and-slots/
你不必局限於Qt widget提供的信號,你可以使用Signal類來創建自己的信號。下面是一個定義的簡單例子:
1 from PySide.QtCore import Signal 2 tapped = Signal()
然后,當對象需要觸發信號的條件滿足時,你可以使用信號的emit方法,來發出信號調用關聯的槽。
thing.tapped.emit()
這樣做有兩個優點:第一,允許用戶和你定義的對象隨意交互;第二,讓你的對象使用更加靈活,讓自己的代碼定義動作行為的影響。
一個簡單的PySide信號例子
我們來定義一個簡單的PunchingBag類,它只做一件事情,當punch被調用時,發出punched信號:
1 from PySide.QtCore import QObject, Signal, Slot 2 3 class PunchingBag(QObject): 4 ''' Represents a punching bag; when you punch it, it 5 emits a signal that indicates that it was punched. ''' 6 punched = Signal() 7 8 def __init__(self): 9 # Initialize the PunchingBag as a QObject 10 QObject.__init__(self) 11 12 def punch(self): 13 ''' Punch the bag ''' 14 self.punched.emit()
代碼非常的簡單:PunchingBag繼承自QObject,所以它可以發出信號;它有一個稱為punched的信號,不攜帶任何數據;並且他有一個僅僅發出punched信號的punch方法。
為了讓PunchingBag更豐富一些,我們需要將它的punched信號和一個槽連接。槽簡單的輸出“Bag was punched”。
1 @Slot() 2 def say_punched(): 3 ''' Give evidence that a bag was punched. ''' 4 print('Bag was punched.') 5 6 bag = PunchingBag() 7 # Connect the bag's punched signal to the say_punched slot 8 bag.punched.connect(say_punched) 9 10 # Punch the bag 10 times 11 for i in range(10): 12 bag.punch()
攜帶數據的PySide信號
創建信號可以完成一個非常有用的事情——攜帶數據。例如,你可以創建一個攜帶整數或者字符串的信號:
updated = Signal(int)
updated = Signal(str)
這個數據類型可以是任何Python的類型名或定義了C++類型的字符串。因為教程不假設有任何C++的知識,故我們只使用Python類型。
例子:一個發送信號的圓
我們用x,y和r定義一個圓,x、y是圓中心的坐標,r是半徑。我們想要當圓被改變大小時,發送一個信號resized;當圓被移動時,也發送一個信號moved。雖然我們可以在信號的槽中檢測圓的大小和位置,但是使用信號發送這些信息會更加方便。
1 from PySide.QtCore import QObject, Signal, Slot 2 3 class Circle(QObject): 4 ''' Represents a circle defined by the x and y 5 coordinates of its center and its radius r. ''' 6 # Signal emitted when the circle is resized, 7 # carrying its integer radius 8 resized = Signal(int) 9 # Signal emitted when the circle is moved, carrying 10 # the x and y coordinates of its center. 11 moved = Signal(int, int) 12 13 def __init__(self, x, y, r): 14 # Initialize the Circle as a QObject so it can emit signals 15 QObject.__init__(self) 16 17 # "Hide" the values and expose them via properties 18 self._x = x 19 self._y = y 20 self._r = r 21 22 @property 23 def x(self): 24 return self._x 25 26 @x.setter 27 def x(self, new_x): 28 self._x = new_x 29 # After the center is moved, emit the 30 # moved signal with the new coordinates 31 self.moved.emit(new_x, self.y) 32 33 @property 34 def y(self): 35 return self._y 36 @y.setter 37 def y(self, new_y): 38 self._y = new_y 39 # After the center is moved, emit the moved 40 # signal with the new coordinates 41 self.moved.emit(self.x, new_y) 42 43 @property 44 def r(self): 45 return self._r 46 47 @r.setter 48 def r(self, new_r): 49 self._r = new_r 50 # After the radius is changed, emit the 51 # resized signal with the new radius 52 self.resized.emit(new_r)
注意以下幾點:
- Circle繼承自QObject所以可以發送信號
- 同樣的信號可以在不同地方發送
現在我們定義一些連接Circle的信號的槽。還記得我們上次提過的@Slot修飾符(decorator)嗎?現在我們來看看如何接收攜帶了數據的信號。為了接收信號,我們簡單的將其定義為與信號一樣的結構。
1 # A slot for the "moved" signal, accepting the x and y coordinates 2 @Slot(int, int) 3 def on_moved(x, y): 4 print('Circle was moved to (%s, %s).' % (x, y)) 5 6 # A slot for the "resized" signal, accepting the radius 7 @Slot(int) 8 def on_resized(r): 9 print('Circle was resized to radius %s.' % r)
非常的簡單直觀。更多信息可以參考Python decorators,或者來學習這篇文章Python Decorators Overview。最后我們完成這個Circle,連接信號槽,移動並改變它的大小。
1 c = Circle(5, 5, 4) 2 3 # Connect the Circle's signals to our simple slots 4 c.moved.connect(on_moved) 5 c.resized.connect(on_resized) 6 7 # Move the circle one unit to the right 8 c.x += 1 9 10 # Increase the circle's radius by one unit 11 c.r += 1
當運行腳本的時候,你的結果應該是:
Circle was moved to (6, 5).
Circle was resized to radius 5.
現在我們對信號和槽有了更深入的了解,可以准備使用一些更高級的widgets了。下一個教程開始討論QListWidget和QListView,兩種創建表框(list box)控件的方法。
By Ascii0x03
轉載請注明出處:http://www.cnblogs.com/ascii0x03/p/5500933.html
