所有的GUI应用程序都是基于事件驱动的。事件主要由应用程序的用户产生,但也可以由其他方式生成。
比如,网络连接,定时器。为了对事件作出响应,系统会产生一个特定的信号。这个信号可视为PyQt库中系统事件的代表。
要处理信号,需将一个类的函数或方法(PyQt中称之为"slot")与之相关联。当事件触发时,该函数或方法被调用,成为信号 的处理程序。
使用继承自QObject类的connect()方法来指定信号的处理程序。调用格式为:
connect(slot[, type=PyQt5.QtCore.Qt.AutoConnection[, no_receiver_check=False]])
参数:
slot – 可调用的函数或另一个信号
type – 要连接的类型。程序应用到多线程编程时,要特别注意这个参数。type的可选值有:
AutoConnection,0:默认值。
如果信号和处理程序在同一线程,等同于DirectConnection;如果不在同一线程,则等同于QueedConnection。
DirectConnection, 1:
信号触发后,处理程序立即在源数据流(source stream)中执行。
QueuedConnection, 2:
信号触发后进行处理队列,处理程序在信号接收方执行。
BlockingQueuedConnection, 4:
类似于QueuedConnection,但在处理程序执行时,线程处于阻塞状态 。需要注意的是信号和处理程序必须在不同线程。UniqueConnection,0x80:表明处理程序只能指定一次。该值可以和前面的值进行组合应用。
no_receiver_check – suppress the check that the underlying C++ receiver instance still exists and deliver the signal anyway.(禁止检查底层C ++接收器实例是否仍然存在,并传递信号。)
例1:
将on_clicked_button ()函数作为button按钮clicked信号处理程序的代码:
button.clicked.connect(on_clicked_button)
信号可以有不同数量的参数,参数可以为任何类型。在一个类中,可以存在信号名相同,但参数不同的多个信号。这时的调用方式为在信号之后加方括号([ ]) ,方括号内为接收到的数据类型。可以采用类型符号或该类型的英文字符串。
button.clicked[bool].connect(on_clicked_button)
button.clicked["bool].connect(on_clicked_button)
可以给一个信号指定多个处理程序。见下例:
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
import sys
def on_clicked():
print("按钮按下: on_clicked ()被调用")
class MyClass():
def __init__(self, x=0):
self.x = x
def __call__(self):
print("按钮按下: MyClass .__ call __ ()")
print("x =", self.x)
def on_clicked(self):
print("按钮按下: MyClass.on_clicked ()")
obj = MyClass()
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("点击鼠标")
# 指定处理程序
button.clicked.connect(on_clicked)
# 指定处理程序为类的方法
button.clicked.connect(obj.on_clicked)
# 指定处理程序为类实例
button.clicked.connect(MyClass(10))
# 指定处理程序为匿名函数
button.clicked.connect(lambda: MyClass(5)())
button.show()
sys.exit(app.exec_())
程序的输出为:
按钮按下: on_clicked ()被调用
按钮按下: MyClass.on_clicked ()
按钮按下: MyClass .__ call __ ()
x = 10
按钮按下: MyClass .__ call __ ()
x = 5
PyQt5中有很多函数可作为信号的处理程序,这些函数称之为slot。
只要在函数定义前加上装饰符@pyqtSlot,任何自定义函数都可变为slot。格式为:
@pyqtSlot(types[, name[, result]])
types – the types that define the C++ signature of the slot. Each type may be a Python type object or a string that is the name of a C++ type(定义slot的C++签名。类型可以是Python的类型也可以是C_++类型的英文字符串).
name – the name of the slot that will be seen by C++. If omitted the name of the Python method being decorated will be used.(C++中可见的slot名称. 如果省略,将使用被装饰的函数名. )
result – the type of the result and may be a Python type object or a string that specifies a C++ type. (函数结果的类型。可以是Python的类型也可以是C_++类型的英文字符串)
例2:
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
import sys
class MyClass(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
@QtCore.pyqtSlot()
def on_clicked(self):
print("按钮按下. slot on_clicked()")
@QtCore.pyqtSlot(bool, name="myslot")
def on_clicked2(self, status):
print("按钮按下. slot myslot(bool)", status)
obj = MyClass()
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("点击鼠标")
button.clicked.connect(obj.on_clicked)
button.clicked.connect(obj.myslot)
button.show()
sys.exit(app.exec_())
程序输出:
按钮按下. slot on_clicked()
按钮按下. slot myslot(bool) False
PyQt中没有强制将信号的处理函数转化成slot,但推荐这样做,因为调用slot的速度快。