PyQt5学习笔记---信号与槽

注:信号与槽中信号和槽的关系

  1. 一个信号可以连接多个槽
  2. 一个信号可以连接另一个信号
  3. 信号参数可以是任何Python类型参数
  4. 一个槽可以监听多个信号
  5. 信号与槽的连接方式可以是同步连接,也可以是异步连接、信号与槽的连接可能是跨线程、信号可能会断开。

定义信号

       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()
  • 信号与槽的在细分化
  1. 内置信号与槽函数
  2. 内置信号和自定义槽函数
  3. 自定义信号和内置槽函数
  4. 自定义信号和槽函数
#自定义信号与槽
# -*- 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_())

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章