Qt中的信号与槽机制简介
信号与槽是Qt的核心机制,是各个控件与窗口对象之间相互通信的基础。不论是希望控件与住窗口之间的通信,实现点击、选择等操作触发相应的窗口对象槽函数,还是多个窗口对象之间的通信,实现多个界面的链接,都需要应用信号槽机制。理解并熟练应用信号槽是Qt开发中重要的一环。
PyQt5中的信号与槽的主要特点
- 一个信号可以连接多个槽,一个槽也可以监听多个信号
- 信号与信号之间也可以互相连接
- 信号与槽的连接可以同步也可以异步
- 信号的参数可以是任意合法Python类型
理解信号槽机制
信号可以理解为广播,当信号事件(如点击、刷新、鼠标操作或者手动激发自定义信号)发生时,所有的对象(窗口、控件)都可以观察到这个信号,但是是否对该信号的激发做出反应,取决于与信号的连接与否。相互连接的信号与对象槽在信号激发时调用对应的槽函数,对信号的激发进行处理。这就是Qt中信号与槽的本质。
信号的激发与调用其实就是一个指令,指示程序做一些特定的事,这些事包含在槽函数中,只不过这个指令的发出到执行过程是自动化的,隐式的。
在QtDesigner中编辑信号与槽
使用Qt自带的信号与槽
我们首先在QtDesigner中创建一个ui文件,在中间放置一个按钮,我们想要实现点击按钮,关闭窗口的功能,首先点击Edit——编辑信号/槽
把光标移动到按钮上,按住左键,拖动到窗口的空白处
这时会弹出一个配置连接窗口,选中左下角的“显示从QWidget继承的信号和槽”,会看到有很多自带的信号与槽;
这时我们选择左边的发出对象的信号“clicked()”,同时选择右边接收对象的槽“close()”,就完成了信号与槽的连接(connected)
这个时候,就会有一条从按钮到窗口的红色线条,说明连接成功
这个时候我们ctrl+R运行,就会发现,这个窗口实现了我们想要的功能
自定义信号与槽
除了QWidget自带的信号与槽,我们还可以自定义信号与槽,实现更多更广泛的功能
这里举一个我实现的模拟铁路售票系统的例子,我们要实现点击“登录”按钮后,调用login_fun()函数,测试登录信息,与数据库中的信息比对,如果用户存在且密码正确,即向用户展示主界面
首先,选中右侧对象查看器中窗口对象,右键点击“改变信号/槽”
在弹出的窗口,点击“+”,输入函数名,新建槽函数
这样,我们就建好了槽函数,把它与“登录”按钮的“click()”信号连接,并在驱动程序中编辑MyMainwindow类时给出login_fun()函数的定义
def login_fun(self):
'''登录槽函数'''
phone=self.lineEdit.text()
password=self.lineEdit_2.text()
login_sql = "select keyword from passenger where(phone_number='{}')".format(phone)
cursor.execute(login_sql)
password_database = cursor.fetchone()
if password_database==None: # 用户不存在或者是管理员账户
admin_login_sql="select password from admin where(admin_id='{}')".format(phone)
cursor.execute(admin_login_sql)
admin_password_database=cursor.fetchone()
if admin_password_database==None:
QMessageBox.information(self, "提示", """用户不存在!""")
return
if password==admin_password_database[0]:
QMessageBox.information(self, "提示", """登录成功!""")
import admin_main_interface_pre
self.four = admin_main_interface_pre.MyMainWindow()
self.signal_phone.connect(self.four.aget_phone)
self.signal_phone.emit(phone)
self.signal_password.connect(self.four.aget_password)
self.signal_password.emit(password)
self.signal_left.connect(self.four.astart_left)
self.signal_left.emit("start")
self.four.show()
else:
QMessageBox.information(self, "提示", """用户不存在!""")
if password==admin_password_database[0]:
self.close()
self.lineEdit_2.clear()
return
if password == password_database[0]: # 登录成功,进入主界面
QMessageBox.information(self, "提示", """登录成功!""")
import main_interface_pre
self.two=main_interface_pre.MyMainWindow()
self.signal_phone.connect(self.two.get_phone)
self.signal_phone.emit(phone)
self.signal_password.connect(self.two.get_password)
self.signal_password.emit(password)
self.signal_left.connect(self.two.start_left)
self.signal_left.emit("start")
self.two.show()
self.close()
else: # 密码错误
QMessageBox.warning(self, "提示","""密码错误,请重新输入!""")
self.lineEdit_2.clear()
return
为了连接另一个界面,并给另一个界面传递一些信息,我们需要在调用界面自定义信号
signal_phone=pyqtSignal(str) # 传给主界面账号、密码等信息
signal_password=pyqtSignal(str)
signal_left=pyqtSignal(str) # 激发显示欢迎语句的槽函数
并在槽函数中的适当位置将这些信号与被调用窗口连接并激发这些信号
self.four = admin_main_interface_pre.MyMainWindow()
self.signal_phone.connect(self.four.aget_phone)
self.signal_phone.emit(phone)
self.signal_password.connect(self.four.aget_password)
self.signal_password.emit(password)
self.signal_left.connect(self.four.astart_left)
self.signal_left.emit("start")
传递给emit函数的参数会原封不动地传递给槽函数,座位槽函数的参数
这样,我们就可以在被调用窗口中定义这些槽函数,并接收来自调用窗口传递的参数
至此,我们就实现了我们需要的功能