zl程序教程

您现在的位置是:首页 >  其它

当前栏目

PyQT信号与槽

信号 Pyqt
2023-09-14 09:10:02 时间

信号与槽机制是PyQT中的一大特色,信号用于发射信号,而与之绑定的槽函数在接受到信号之后便开始执行。
先来看一个最简单的例子

import sys
from PyQt5.QtWidgets import QMessageBox,QPushButton,QApplication,QWidget

app=QApplication(sys.argv)
widget=QWidget()

def showMsg():
    QMessageBox.information(widget,'信息提示框','Ok 弹出测试信息')

btn=QPushButton('测试点击按钮',widget)

btn.clicked.connect(showMsg)

widget.show()
sys.exit(app.exec_())

在上面的代码中,clicked是信号,showMsg是槽,当鼠标单击btn时,clicked信号发生,与之绑定的showMsg执行。

自定义信号与槽

如下代码:

from PyQt5.QtCore import QObject,pyqtSignal

#信号对象
class QTypeSignal(QObject):
    #定义一个信号
    # sendmsg = pyqtSignal(object)
    #todo 优化 多个参数传递
    sendmsg=pyqtSignal(str,str)


    def __init__(self):
        super(QTypeSignal, self).__init__()

    def run( self ):
        #发射信号
        #self.sendmsg.emit('hell')

        #todo 优化 发射多个参数
        self.sendmsg.emit('第一参数','第二个参数')


#槽对象
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()
    #槽对象中的槽函数
    # def get( self,msg ):
    #     print("QSlot get msg => " + msg)

    #todo 优化 多个参数
    def get( self,msg1,msg2 ):
        print("QSlot get msg => " + msg1+' '+msg2)


if __name__ == '__main__':
    #实例化信号对象
    send=QTypeSignal()
    #实例化槽对象
    slot=QTypeSlot()

    #1
    print('_____-把信号绑定到槽函数上_)___')
    send.sendmsg.connect(slot.get)

    send.run()

    print('_____-把信号与槽函数解绑_)___')
    send.sendmsg.disconnect(slot.get)

    send.run()

在上边的代码中,信号对象定义了sendmsg信号,并且在run函数中发射该信号,通过send.sendmsg.connect(slot.get),将sendmsg信号与slot.get槽函数绑定,send.sun()之后,便会发现有打印信息输出,之后解绑,发现run之后并没有输出。

参数传递

下面的代码则显示了如何通过信号传递不同的参数

from PyQt5.QtCore import QObject,pyqtSignal

class CusSignal(QObject):
    #无参数的信号
    signal1=pyqtSignal()
    #带一个参数(整数)的信号
    signal2=pyqtSignal(int)
    #带两个参数(整数,字符串)的信号
    signal3=pyqtSignal(int,str)
    #带一个参数(列表)的信号
    signal4=pyqtSignal(list)
    #带一个参数(字典)的信号
    signal5=pyqtSignal(dict)
    #带(整数 字符串)或者(字符串)的信号
    signal6=pyqtSignal([int,str],[str])

    def __init__(self,parent=None):
        super(CusSignal, self).__init__(parent)

        #信号与槽函数的链接
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall3)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[int,str].connect(self.signalCall6)
        self.signal6[str].connect(self.signalCall7)

        #信号发射
        self.signal1.emit()
        self.signal2.emit(1)
        self.signal3.emit(1,'第三个')
        self.signal4.emit([1,2,3,4])
        self.signal5.emit({"name":'JIA','age':'21'})
        self.signal6[int,str].emit(1,"第六")
        self.signal6[str].emit('第六')

    #槽函数
    def signalCall1( self ):
        print("signal1 emit")
    def signalCall2( self,val ):
        print('signal2 emit,value:',val)
    def signalCall3( self,val,text ):
        print('signall3 emit,value:',val,text)
    def signalCall4( self,val ):
        print('signal4 emit,value:',val)
    def signalCall5( self,val ):
        print('signal5 emit,value',val)
    def signalCall6( self,val,text ):
        print('signal6 emit,value',val,text)
    def signalCall7( self,val ):
        print('signal6 ovetload emit',val)

if __name__ == '__main__':
    custSignal=CusSignal()

即,在定义信号时,同时要说明该信号携带的参数,比如signal3=pyqtSignal(int,str),signal3携带一个int信号和一个str信号,
self.signal3.emit(1,‘第三个’),这句话说明signal3信号发射,并且携带有1这个int信号和’第三个’这个str信号,通过self.signal3.connect(self.signalCall3)语句,signal3信号和signalCall3槽绑定,并且signalCall3通过如下语句接收信号传递的参数
def signalCall3( self,val,text ):

自定义参数的传递

当信号发出的参数个数与槽函数接受的参数个数不一,应该如何解决这个问题呢,这里提供两种解决方法:
第一种:lamdba表达式
第二种:使用functools中的partial函数

import sys
from PyQt5.QtWidgets import *
from functools import partial

class WinForm(QMainWindow):
    def __init__(self,parent=None):
        super(WinForm, self).__init__(parent)
        #实例化两个按钮
        button1=QPushButton('Button1')
        button2=QPushButton('Button2')

        #todo 第一种方法
        #单击信号关联槽函数,利用Lanbda表达式传递一个参数
        # button1.clicked.connect(lambda :self.onButtonClick(1))
        # button2.clicked.connect(lambda :self.onButtonClick(2))
        #
        #todo 第二种方法
        button1.clicked.connect(partial(self.onButtonClick, 1))
        button2.clicked.connect(partial(self.onButtonClick, 2))

        #实例化窗口
        main=QWidget()

        #设置窗口的布局,并向其中添加控件
        layout=QHBoxLayout(main)
        layout.addWidget(button1)
        layout.addWidget(button2)

        #设置为中央控件
        self.setCentralWidget(main)
    def onButtonClick( self,n ):

        #弹窗信息提示框,输出被点击的信息
        print("Button {0}".format(n))
        QMessageBox.information(self,'信息提示框','Button {0}'.format(n))
if __name__ == '__main__':
    app=QApplication(sys.argv)
    form=WinForm()
    form.show()
    sys.exit(app.exec_())

如上图代码
button1.clicked.connect(lambda :self.onButtonClick(1))
button2.clicked.connect(lambda :self.onButtonClick(2))
用lambda函数实现了整数1,2的传递。
button1.clicked.connect(partial(self.onButtonClick, 1))
button2.clicked.connect(partial(self.onButtonClick, 2))
用partial实现了整数1,2的传递。

装饰器信号与槽

链接