博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PyQt5-信号与槽
阅读量:4964 次
发布时间:2019-06-12

本文共 8842 字,大约阅读时间需要 29 分钟。

信号与槽我们之前案例中已涉及,信号(Signal)和槽(Slot)是Qt中的核心机制,也是PyQt变成中对象之间进行通信的机制;

在Qt中,每一个QObject对象和PyQt中所有继承自QWidget的控件都支持信号和槽;

挡信号发射时,连接槽函数将会被自动执行(与事件和回调函数类似); PyQt5中信号和槽通过connect()方法来连接;

PyQt中针对窗口类控件有很多内置的信号,也可以自定义信号;信号与槽有以下几个特点:

1、一个信号可以连接多个槽函数

2、一个信号可以连接另一个信号

3、一个槽可以监听多个信号

4、信号和槽的连接可能会跨线程

5、连接方式可以是同步或者异步

6、信号与槽可以是多对多关系

信号的定义:

PyQt来自定义一个信号,则使用PyQt5.QtCore.pyqtSignal()函数完成,使用该函数可以将信号定义为类的一个属性;

信号必须在类创建时定义,不能在类定以后作为类的属性动态添加进去;types参数表示定义信号时参数的数据类型,namc参数

表示信号名字,该参数缺省时使用类的属性名字;pyqtSignal()函数可以传递多个参数,并指定信号传递参数的类型,参数类型是标准的Python数据类型(字符串、日期、布尔类型,数字,列表,元组和字典)

信号操作:

使用connect()方法来将信号和槽函数绑定;disconnect()函数可以解除绑定;

emit()方法用于发射信号;

例如:

1 #信号与槽(QTabWidget略) 2 from PyQt5.QtWidgets import  QComboBox,QTableView,QAbstractItemView,QHeaderView,QTableWidget, QTableWidgetItem, QMessageBox,QListWidget,QListWidgetItem, QStatusBar,  QMenuBar,QMenu,QAction,QLineEdit,QStyle,QFormLayout,   QVBoxLayout,QWidget,QApplication ,QHBoxLayout, QPushButton,QMainWindow,QGridLayout,QLabel 3 from PyQt5.QtGui import QIcon,QPixmap,QStandardItem,QStandardItemModel,QCursor,QFont,QBrush,QColor 4 from PyQt5.QtCore import QStringListModel,QAbstractListModel,QModelIndex,QSize,Qt,QObject,pyqtSignal 5  6 import sys 7 class SiganlObj(QObject): 8      sendMsg=pyqtSignal(object) #定义信号 9 10      def __init__(self):11          super(SiganlObj, self).__init__()12      def run(self):13          self.sendMsg.emit("Hello")#发射信号14 15 class TypeSlot(QObject):#定义槽对象16      def __init__(self):17          super(TypeSlot, self).__init__()18      def get(self,msg):#定义槽函数19          print(">>",msg)20 21 if __name__=='__main__':22     send=SiganlObj()23     slot=TypeSlot()24     send.sendMsg.connect(slot.get)#绑定信号和槽函数25     send.run()#发信号

 再次修改上面实例:

例如,通过按钮来发送消息:

1 #信号与槽(QTabWidget略) 2 from PyQt5.QtWidgets import  QComboBox,QTableView,QAbstractItemView,QHeaderView,QTableWidget, QTableWidgetItem, QMessageBox,QListWidget,QListWidgetItem, QStatusBar,  QMenuBar,QMenu,QAction,QLineEdit,QStyle,QFormLayout,   QVBoxLayout,QWidget,QApplication ,QHBoxLayout, QPushButton,QMainWindow,QGridLayout,QLabel 3 from PyQt5.QtGui import QIcon,QPixmap,QStandardItem,QStandardItemModel,QCursor,QFont,QBrush,QColor 4 from PyQt5.QtCore import QStringListModel,QAbstractListModel,QModelIndex,QSize,Qt,QObject,pyqtSignal 5  6 import sys 7 class SiganlObj(QObject): 8      sendMsg=pyqtSignal(object,object) #定义信号(无参数或者多个参数都可以) 9 10      def __init__(self):11          super(SiganlObj, self).__init__()12      def run(self):13          self.sendMsg.emit("Hello",'JONES')#发射信号14 15 class TypeSlot(QObject):#定义槽对象16      def __init__(self):17          super(TypeSlot, self).__init__()18      def get(self,msg,s):#定义槽函数19          print(">>",msg,s)20 21 class Win(QWidget):22     def __init__(self,parent=None):23         super(Win, self).__init__(parent)24         self.btn=QPushButton("点击",self)25         self.btn.clicked.connect(self.btnFn)#点击按钮,执行btnFn方法26         self.send = SiganlObj()#信号对象27         self.slot = TypeSlot()#槽对象28         self.send.sendMsg.connect(self.slot.get)  # 绑定信号和槽函数29     def btnFn(self):30         self.send.run()  # 发信号31 32 if __name__=='__main__':33 34     app=QApplication(sys.argv)35     win = Win()36     win.show()37     sys.exit(app.exec_())

 例如:点击按钮发送多个消息,定义多个槽

1 #信号与槽(QTabWidget略)多个信号与多个槽 2 from PyQt5.QtWidgets import  QComboBox,QTableView,QAbstractItemView,QHeaderView,QTableWidget, QTableWidgetItem, QMessageBox,QListWidget,QListWidgetItem, QStatusBar,  QMenuBar,QMenu,QAction,QLineEdit,QStyle,QFormLayout,   QVBoxLayout,QWidget,QApplication ,QHBoxLayout, QPushButton,QMainWindow,QGridLayout,QLabel 3 from PyQt5.QtGui import QIcon,QPixmap,QStandardItem,QStandardItemModel,QCursor,QFont,QBrush,QColor 4 from PyQt5.QtCore import QStringListModel,QAbstractListModel,QModelIndex,QSize,Qt,QObject,pyqtSignal 5  6 import sys 7 #信号 8 class ObjSignal(QObject): 9     msg_1=pyqtSignal()#无参数消息10     msg_2=pyqtSignal([int],[str])#一个参数的消息,参数为str或者int类型11     msg_3=pyqtSignal(str,list)#两个参数消息12     msg_4=pyqtSignal(str,dict)13 14 #槽15 class ObjSlot(QObject):16     def __init__(self):17         super(ObjSlot, self).__init__()18     def slot_1(self):19         print("无参数的槽!")20 21     def slot_2(self,param):22         print("[str/int]参数的槽!>>",param)23 24     def slot_2_1(self, param):25         print("[str/int]参数的槽!>>", param)26 27     def slot_3(self,param1,param2):28         print("str +list参数的槽!>>",param1,param2)29 30     def slot_4(self,str,dict):31         print("str,dict参数的槽!",str,dict)32 33 34 35 class Win(QWidget):36     def __init__(self,parent=None):37         super(Win, self).__init__(parent)38         self.btn=QPushButton("点击",self)39         self.signal = ObjSignal()  # 信号对象40         self.solt = ObjSlot()  # 槽对象41 42         self.signal.msg_1.connect(self.solt.slot_1)#无参数43         self.signal.msg_2[int].connect(self.solt.slot_2)#str/int一个参数44         self.signal.msg_2[str].connect(self.solt.slot_2_1)  # str/int一个参数45         self.signal.msg_3.connect(self.solt.slot_3)#str,int 两个参数46         self.signal.msg_4.connect(self.solt.slot_4)#str,dict,str两个参数47 48         self.btn.clicked.connect(self.btnFn)#点击按钮,执行btnFn方法49 50     def btnFn(self):51         #self.signal.msg_1.connect(self.solt.slot_1)#注意:如果在这个位置来连接,此时会出现,点击一次 结果显示一次,点击第二次,显示两次,第三次,则4.。。。。52         self.signal.msg_1.emit()53         self.signal.msg_2.emit('abc')54         self.signal.msg_2.emit(10)55         self.signal.msg_3.emit('A',[10,20,30,40])56         self.signal.msg_4.emit('字典参数',{
"a":"ABC","b":"SDF"})57 58 if __name__=='__main__':59 60 app=QApplication(sys.argv)61 win = Win()62 win.show()63 sys.exit(app.exec_())

注意上面的实例中,消息与槽的连接代码位置放在不同地方是有差异的;也要注意:不允许参数pyqtSignal([int,str],[str,int])这种可选参数,【int,str】即表示该位置参数类型既可以是int也可以是str类型;

 

例如,使用自定义参数

1 #信号与槽(QTabWidget略)自定义参数 2 from PyQt5.QtWidgets import  QComboBox,QTableView,QAbstractItemView,QHeaderView,QTableWidget, QTableWidgetItem, QMessageBox,QListWidget,QListWidgetItem, QStatusBar,  QMenuBar,QMenu,QAction,QLineEdit,QStyle,QFormLayout,   QVBoxLayout,QWidget,QApplication ,QHBoxLayout, QPushButton,QMainWindow,QGridLayout,QLabel 3 from PyQt5.QtGui import QIcon,QPixmap,QStandardItem,QStandardItemModel,QCursor,QFont,QBrush,QColor 4 from PyQt5.QtCore import QStringListModel,QAbstractListModel,QModelIndex,QSize,Qt,QObject,pyqtSignal 5  6 import sys 7 class Win(QWidget): 8     def __init__(self,parent=None): 9         super(Win, self).__init__(parent)10         self.btn1=QPushButton("点击1",self)11         self.btn1.move(20,40)12         self.btn1.clicked.connect(lambda :self.btnFn(1))#点击按钮,执行btnFn方法13 14         self.btn2 = QPushButton("点击2", self)15         self.btn2.move(140,40)16         self.btn2.clicked.connect(lambda: self.btnFn(2))  # 点击按钮,执行btnFn方法17 18 19 20     def btnFn(self,flag):21         if flag==1:22             print("点击了第一个按钮")23         else:24             print("点击了第二个按钮")25 26 27 if __name__=='__main__':28 29     app=QApplication(sys.argv)30     win = Win()31     win.show()32     sys.exit(app.exec_())

 

 

装饰器信号与槽:

即通过装饰器来定义信号和槽函数;

1 @PyQt5.QtCore.pyqtSlot(参数)2 def on_发送者对象名称_发射信号名称(self,参数):3 pass

 以上定义的信号和槽有效,则前提是执行了

QMetaObject.connectSlotsByName(QObject)

"发送者对象名称"即让按钮、下拉列表以及其他各种组件通过setObjectName方法设置的名称,

例如:

1 def __init__(self,parent=None):2     self.okButton.clicked.connect(self.okButton_clicked)3 def okButton_clicked(self):4     print('单击ok按钮!')

等同于下面几行代码:

1 @QtCore.pyqtSlot()2 def on_okButton_clicked(self):3     print('单击了ok按钮')

 

信号与槽的连接与断开

槽的断开通过disconnect来断开连接;

1 #信号与槽(QTabWidget略)信号的断开与连接 2 from PyQt5.QtWidgets import  QComboBox,QTableView,QAbstractItemView,QHeaderView,QTableWidget, QTableWidgetItem, QMessageBox,QListWidget,QListWidgetItem, QStatusBar,  QMenuBar,QMenu,QAction,QLineEdit,QStyle,QFormLayout,   QVBoxLayout,QWidget,QApplication ,QHBoxLayout, QPushButton,QMainWindow,QGridLayout,QLabel 3 from PyQt5.QtGui import QIcon,QPixmap,QStandardItem,QStandardItemModel,QCursor,QFont,QBrush,QColor 4 from PyQt5.QtCore import QStringListModel,QAbstractListModel,QModelIndex,QSize,Qt,QObject,pyqtSignal 5  6 import sys 7 class SlotObj(QObject): 8     # 信号 9     slot_1 = pyqtSignal()10     slot_2 = pyqtSignal(str)11     def __init__(self,parent=None):12         super(SlotObj, self).__init__(parent)13         '''14         注意:容易犯错的地方是,将15         信号定义在该方法中;信号应该定义在类中16         '''17         #槽18         self.slot_1.connect(self.call_1)19         self.slot_2[str].connect(self.call_2)20 21         #发送消息22         self.slot_1.emit()23         self.slot_2.emit("HAHA!")24 25         #断开连接26         self.slot_1.disconnect(self.call_1)27 28         #再次发送消息29         self.slot_1.emit()#已经将其断开,则无法发送信息号30         self.slot_2.emit("HAHA!")31 32     def call_1(self):33         print('call_1')34     def call_2(self,str):35         print('call_2A>>',str)36 37 if __name__=='__main__':38     SlotObj()

 

转载于:https://www.cnblogs.com/ygzhaof/p/10118455.html

你可能感兴趣的文章
C3P0 WARN: Establishing SSL connection without server's identity verification is not recommended
查看>>
iPhone在日本最牛,在中国输得最慘
查看>>
动态方法决议 和 消息转发
查看>>
js 基础拓展
查看>>
C#生成随机数
查看>>
Android应用程序与SurfaceFlinger服务的连接过程分析
查看>>
Java回顾之多线程
查看>>
机电行业如何进行信息化建设
查看>>
9、总线
查看>>
Git 笔记 - section 1
查看>>
2018 Multi-University Training Contest 10 - Count
查看>>
HDU6203 ping ping ping
查看>>
《人人都是产品经理》书籍目录
查看>>
如何在git bash中运行mysql
查看>>
OO第三阶段总结
查看>>
构建之法阅读笔记02
查看>>
DataTable和 DataRow的 区别与联系
查看>>
检索COM 类工厂中CLSID 为 {00024500-0000-0000-C000-000000000046}的组件时失败
查看>>
mysql数据库中数据类型
查看>>
Fireworks基本使用
查看>>