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)