• PyQt5-信号与槽


    信号与槽我们之前案例中已涉及,信号(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()
  • 相关阅读:
    与众不同 windows phone (39)
    与众不同 windows phone (38)
    与众不同 windows phone (37)
    与众不同 windows phone (36)
    与众不同 windows phone (35)
    与众不同 windows phone (34)
    重新想象 Windows 8 Store Apps 系列文章索引
    重新想象 Windows 8 Store Apps (71)
    重新想象 Windows 8 Store Apps (70)
    重新想象 Windows 8 Store Apps (69)
  • 原文地址:https://www.cnblogs.com/ygzhaof/p/10118455.html
Copyright © 2020-2023  润新知