注:信号与槽中信号和槽的关系
- 一个信号可以连接多个槽
- 一个信号可以连接另一个信号
- 信号参数可以是任何Python类型参数
- 一个槽可以监听多个信号
- 信号与槽的连接方式可以是同步连接,也可以是异步连接、信号与槽的连接可能是跨线程、信号可能会断开。
定义信号
PyQt的内置信号是自动定义的,使用PyQt5.QtCore.pyqtSignal()可以为QObject创建一个信号,使用pySignal()函数可以将信号定义为类的属性。
信号必须在类创建时定义,不能在类创建后作为属性动态添加进来。且必须在QObject的子类中定义。
信号可传递多个参数,并制定信号参数传递的类型,参数是标准的python类型(字符串、日期、布尔、数字、列表、元组、字典)
信号基本使用操作
使用pySignal()创建一个自定义信号,使用connect()连接信号到槽函数、使用disconnect()断开信号和槽的连接,使用emit()发射信号
- 内置信号与槽的使用
指的是在发射信号时,使用窗口控件的函数,而非自定义函数,通过使用QObject.signal.connect将一个QObject 信号连接到另一个QObject函数
#QObject signal connect
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
app=QApplication([])
widget=QWidget()
def showMsg():
QMessageBox.information(widget,"info","ok,test msg")
btn=QPushButton("test",widget)
btn.clicked.connect(showMsg) #将按钮的内置消息 点击 连接到 showMsg槽函数
widget.show()
sys.exit(app.exec_())
- 自定义信号与槽的使用
指在发射信号时,不使用窗口控件函数,而使用自定义的函数(使用pyqtSignal类实例发射信号)
#自定义信号与槽
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
#信号类
class QTypeSiganl(QObject):
#优先定义带一个参数的信号
sendMsg=pyqtSignal(object)
#定义带两个参数的信号
# sendMsg=pyqtSignal(param1,param)
def __init__(self):
super(QTypeSiganl, self).__init__()
def run(self):
#发射信号并带有参数hello pyqt
self.sendMsg.emit("hello pyqt \n")
#槽函数类
class QTypeSlot(QObject):
def __init__(self):
super(QTypeSlot, self).__init__()
def get(self,msg):
print("QSlot get msg " + msg +"\n")
if __name__ == "__main__":
send=QTypeSiganl()
slot=QTypeSlot()
#连接信号(sendMsg)与槽函数(slot.get)
send.sendMsg.connect(slot.get)
send.run()
#断开连接信号(sendMsg)与槽函数(slot.get)
send.sendMsg.disconnect(slot.get)
#再次发送是不会触发槽函数
send.run()
- 信号与槽的在细分化
- 内置信号与槽函数
- 内置信号和自定义槽函数
- 自定义信号和内置槽函数
- 自定义信号和槽函数
#自定义信号与槽
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WinForm(QWidget):
#自动定义信号不带参数
btn_clicked_signal=pyqtSignal()
def __init__(self):
super(WinForm, self).__init__()
self.resize(300,100)
btn=QPushButton("CLOSE",self)
# #使用空间内置信号和内置槽函数
# btn.clicked.connect(self.close)
# #使用空间内置信号和自定义槽函数
# btn.clicked.connect(self.btn_close)
# #使用内置信号clicked连接到自定义槽函数,发射自定义信号
# btn.clicked.connect(self.btn_clicked)
# #将自定义信号连接到内置槽函数
# self.btn_clicked_signal.connect(self.close)
#使用内置信号clicked连接到自定义槽函数,发射自定义信号
btn.clicked.connect(self.btn_clicked)
# 将自定义信号连接到自定义槽函数
self.btn_clicked_signal.connect(self.btn_close)
#自定义槽函数,槽函数就是一个正常的类的成员函数
def btn_clicked(self):
#发送自定义信号
self.btn_clicked_signal.emit()
def btn_close(self):
self.close()
if __name__=="__main__":
app=QApplication(sys.argv)
demo=WinForm()
demo.show()
sys.exit(app.exec_())
- 信号与槽的高级方式
即自定义信号与槽和自定义传递参数(数据类型为python基本类型)
#自定义信号与槽 高级玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
# #通过类成员变量定义带参数信号
class Siganl(QWidget):
#无参数信号
signal_no_param=pyqtSignal()
#带一个参数(整数)的信号
signal_One_param=pyqtSignal(int)
#带一个参数(整数或字符串)的重载信号
signal_One_param_overload=pyqtSignal([int],[str])
#带两个参数(整数和字符串)的信号
signal_two_param=pyqtSignal(int,str)
# 带两个参数([整数和整数]、[整数和字符串])的重载信号
signal_two_param_overload=pyqtSignal([int,int],[int,str])
#声明一个带列表参数的信号
signal_list_param=pyqtSignal(list)
# 声明一个带字典参数的信号
signal_dict_param=pyqtSignal(dict)
def __init__(self):
super(Siganl, self).__init__()
self.connectSignalSlot()
#定义槽函数
#无参数槽函数
def setValue_NoParam(self):
print("No Param")
#带一个参数(整数)的槽函数
def setValue_One_Param(self,nIndex):
print("setValue One Param %d" % nIndex)
#带一个参数(字符串)的槽函数
def setValue_One_Param_Str(self,szIndex):
print("One Param str %s " % szIndex)
#带两个参数(整数,整数)的槽函数
def setValue_Two_Param(self,x,y):
print("two Param IntInt %d %s" % (x,y))
#带两个参数(整数,字符串)的槽函数
def setValue_Two_Param_Str(self,x,szy):
print("two Param IntStr %d %s" % (x, szy))
def setValue_list_Param(self,listVal):
print("list value ",listVal)
def setValue_dict_Param(self,dictVal):
print("dict value ", dictVal)
#连接信号槽
def connectSignalSlot(self):
#连接无参数
self.signal_no_param.connect(self.setValue_NoParam)
#连接带一个参数的
self.signal_One_param.connect(self.setValue_One_Param)
# 连接带一个参数(整数或字符串)的重载信号
self.signal_One_param_overload[int].connect(self.setValue_One_Param)
# 连接带一个参数(整数或字符串)的重载信号
self.signal_One_param_overload[str].connect(self.setValue_One_Param_Str)
# 连接带两个参数的信号
self.signal_two_param.connect(self.setValue_Two_Param)
# 连接带两个参数(整数和字符串)的信号
self.signal_two_param_overload[int,int].connect(self.setValue_Two_Param)
# 连接带两个参数([整数和字符串])的重载信号
self.signal_two_param_overload[int,str].connect(self.setValue_Two_Param_Str)
self.signal_list_param.connect(self.setValue_list_Param)
self.signal_dict_param.connect(self.setValue_dict_Param)
#发射信号
def mousePressEvent(self, event):
#发射无参信号
self.signal_no_param.emit()
#发射连接带一个参数的信号
self.signal_One_param.emit(1)
# 发射连接带一个参数(整数或字符串)的重载信号
self.signal_One_param_overload[int].emit(2)
# 发射连接带一个参数(整数或字符串)的重载信号
self.signal_One_param_overload[str].emit("ryt")
# 发射连接带两个参数的信号
self.signal_two_param.emit(3,"213123")
# 发射连接带两个参数(整数和字符串)的信号
self.signal_two_param_overload[int,int].emit(1,2)
# 发射连接带两个参数([整数和整数]、[整数和字符串])的重载信号
self.signal_two_param_overload[int,str].emit(4,"qwe")
#发射列表数据信号
litVal=[1,2,3,4]
self.signal_list_param.emit(litVal)
# 发射字典数据信号
dictVal={"N":1,"M":2,"I":3,"J":4}
self.signal_dict_param.emit(dictVal)
if __name__=="__main__":
app=QApplication(sys.argv)
demp=Siganl()
demp.show()
sys.exit(app.exec_())
- 装饰器信号与槽 采用装饰器的方式来定义信号和槽函数。
使用方法
@PyQt5.QtCore.pyqtSlot(参数)
def on_发送者对象名称_发射信号名称(self,参数)
pass
Tips:
发送者对象名称:即用setObjectName函数设置的名称
发射信号名称 :内置信号或者自定义信号的名称
使用上述方法前提是必须先执行下面这句
QMetaObject.connectSlotByName(QObject)
#自定义装饰器信号与槽 高级玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
import sys
class CustWidget(QWidget):
def __init__(self):
super(CustWidget, self).__init__()
self.onBtn=QPushButton("OK",self)
#使用setObjectName设置按钮控件名称
self.onBtn.setObjectName("okButton")
layout=QHBoxLayout(self)
layout.addWidget(self.onBtn)
self.setLayout(layout)
#不能缺少且必须先运行
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_okButton_clicked(self):
print("clicked button")
#带参数槽函数
# @QtCore.pyqtSlot(int)
# def on_inputSpinBox1_valueChanged(self, value):
# self.outputWidget.setText(str(value + self.inputSpinBox2.value()))
if __name__=="__main__":
app=QApplication(sys.argv)
demo=CustWidget()
demo.show()
sys.exit(app.exec_())
- 多线程中信号与槽使用
#自定义信号与槽 高级玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MyWidgt(QWidget):
def __init__(self):
super(MyWidgt, self).__init__()
#创建一个信号,并设置名称、变量、信号与槽
self.thread=MyThread()
self.thread.setIdentify("th1")
#线程中的信号绑定当前类槽函数
self.thread.sinout.connect(self.outText)
self.thread.setVal(6)
def outText(self,text):
print(text)
class MyThread(QThread):
sinout=pyqtSignal(str)
def __init__(self):
super(MyThread, self).__init__()
self.identify=None
def setIdentify(self,text):
self.identify=text
def setVal(self,val):
self.times=int(val)
#运行线程执行run
self.start()
def run(self):
while self.times>0 and self.identify:
self.sinout.emit(self.identify +"===>"+str(self.times))
self.times-=1
if __name__=="__main__":
app=QApplication(sys.argv)
demo=MyWidgt()
demo.show()
sys.exit(app.exec_())