捐助郴维网
感谢您对郴维网的支持,你的支持将是郴维网持续发展的动力!
二维码
×
当前位置:郴维网 >Pyqt5 > 正文
3 2018.04

信号与槽机制

点击次数:1364 更新时间:2018-4-3 12:54:47  【打印此页

信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。 
在linux、windows等 GUI 工具包中,GUI组件都会注册回调函数用于处理组件所触发的动作,通常是注册对应的函数的函数指针。在之前关于Button的文章中提到了信号与槽的机制的使用,通过该机制可以很好的将组件的信号(如button的clocked、toggled、pressed等)和处理该信号的槽关联起来。通过 信号与槽机制,能够让我们很简洁和快速的来完成相关的功能。

信号和槽是用来在对象间传递数据的方法:当一个特定事件发生的时候,signal会被emit出来,slot调用是用来响应相应的signal的。Qt中对象已经包含了许多预定义的 signal(基本组件都有各自特有的预定义的信号),根据使用的场景我们可以添加新的signal。Qt的对象中已经包含了许多预定义的槽函数,但我们也根据使用的场景添加新的槽函数。


信号:

当对象的状态发生改变的时候,信号就由该对象发射 (emit) 出去。当一个信号被发射(emit)时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。 
如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。


槽:

用于接受信号,而且槽只是普通的对象成员函数。当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。


信号和槽的绑定:

通过调用 Qobject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下::

connect(slot[, type=PyQt5.QtCore.Qt.AutoConnection[, no_receiver_check=False]])
Parameters: 
slot – the slot to connect to, either a Python callable or another bound signal.
Type – the type of the connection to make.
No_receiver_check – suppress the check that the underlying C++ receiver instance still exists and deliver the signal anyway.

当信号与槽没有必要继续保持关联时,我们可以使用 disconnect 函数来断开连接。其定义如下:

disconnect([slot])
Parameters: slot – the optional slot to disconnect from, either a Python callable or another bound signal. If it is omitted then all slots connected to the signal are disconnected.

信号和槽的特点:

1、一个信号可以连接到多个槽; 
当信号发出后,槽函数都会被调用,但是调用的顺序是随机的,不确定的。

self.slider.valueChanged.connect(self.pBar.setValue) 
self.slider.valueChanged.connect(self.lcdNumber.display)

Qslider数据的变化同时绑定在setValue()和display()两个槽上。

2、多个信号可以连接到同一个槽; 
其中任何一个信号发出,槽函数都会被执行。

self.buttonOn.clicked.connect(self.showMessage)
self.buttonOff.clicked.connect(self.showMessage)

showMessage()同时绑定在两个button的clicked信号上。

3、信号的参数可以是任何的Python类型; 
如list,dict等python独有的类型。自定义信号的时候举例说明。

4、信号和槽的连接可以被移除; 
比如断开某个特定信号的关联。

self.buttonOn.clicked.connect(self.showMessage)

5、信号可以和另外一个信号进行关联; 
第一个信号发出后,第二个信号也同时发送。比如关闭系统的信号发出之后,同时会发出保存数据的信号。


代码示例:

关于信号和槽的式样代码如下:

#-*- coding:utf-8 -*-
'''
Signal & Slot
'''

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (Qwidget, QLCDNumber, Qslider,QGridLayout,Qlabel,QHBoxLayout, QGroupBox,
    QVBoxLayout, Qapplication,QProgressBar,QPushButton,QMessageBox)


class SignalSlot(Qwidget):

    def __init__(self):
        super(SignalSlot,self).__init__()      
        self.initUI()


    def initUI(self):

        self.controlsGroup = QGroupBox("运行样本")
        self.lcdNumber = QLCDNumber(self)
        self.slider = Qslider(Qt.Horizontal, self)
        self.pBar = QProgressBar(self)
        vbox = QVBoxLayout()
        vbox.addWidget(self.pBar)
        vbox.addWidget(self.lcdNumber)
        vbox.addWidget(self.slider)
        self.controlsGroup.setLayout(vbox)

        controlsLayout = QGridLayout()
        self.label1 = Qlabel("保存状态:")
        self.saveLabel = Qlabel()
        self.label2 = Qlabel("运行状态:")
        self.runLabel = Qlabel()
        self.buttonSave = QPushButton("保存")
        self.buttonRun = QPushButton("运行")
        self.buttonStop = QPushButton("停止")
        self.buttonDisconnect = QPushButton("解除关联")
        self.buttonConnect = QPushButton("绑定关联")

        controlsLayout.addWidget(self.label1,0,0)
        controlsLayout.addWidget(self.saveLabel,0,1)
        controlsLayout.addWidget(self.label2,1,0)
        controlsLayout.addWidget(self.runLabel,1,1)
        controlsLayout.addWidget(self.buttonSave,2,0)
        controlsLayout.addWidget(self.buttonRun,2,1)
        controlsLayout.addWidget(self.buttonStop,2,2)
        controlsLayout.addWidget(self.buttonDisconnect,3,0)
        controlsLayout.addWidget(self.buttonConnect,3,1)

        layout = QHBoxLayout()
        layout.addWidget(self.controlsGroup)
        layout.addLayout(controlsLayout)
        self.setLayout(layout)

        self.buttonRun.clicked.connect(self.buttonSave.clicked)
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
        self.buttonSave.clicked.connect(self.showMessage)
        self.buttonRun.clicked.connect(self.showMessage)
        self.buttonDisconnect.clicked.connect(self.unbindConnection)
        self.buttonConnect.clicked.connect(self.bindConnection)
        self.buttonStop.clicked.connect(self.stop)

        self.setGeometry(300, 500, 500, 180)
        self.setWindowTitle('信号和槽')

    def showMessage(self):
        if self.sender().text() == "保存":
            self.saveLabel.setText("Saved")
        elif self.sender().text() == "运行":
            self.saveLabel.setText("Saved")
            self.runLabel.setText("Running")

    def unbindConnection(self):
        self.slider.valueChanged.disconnect()
    def bindConnection(self):
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
    def stop(self):
        self.saveLabel.setText("")
        self.runLabel.setText("")

if __name__ == '__main__':

    app = Qapplication(sys.argv)
    ex = SignalSlot()
    ex.show()
    sys.exit(app.exec_())

程序运行的结果: 
说明: 这里写图片描述 
控件说明:

控件类型

控件名称

作用

QLCDNumber

lcdNumber

显示slider滑动之后的数据

QProgressBar

pBar

显示slider滑动之后的数据(百分比数据)

Qslider

slider

滑动块调整数据

QPushButton

buttonSave

在saveLabel显示保存的状态”Saved”

QPushButton

buttonRun

在runLabel显示运行的状态”Running”

QPushButton

buttonDisconnect

解除slider.valueChanged信号的绑定

QPushButton

buttonConnect

连接slider.valueChanged信号的绑定

QPushButton

buttonStop

清除saveLabel和runLabel的信息

示例说明: 
程序样本运行的界面逻辑,先设定运行的程序样本数量,然后先保存后运行的逻辑状态。通过slider的滑动来改变progressBar和LCD的显示数据;“保存”按钮保存运行的样本;“运行”按钮运行程序样本;“解除关联”解除slider.valueChanged信号的绑定,此时slider的滑动,不会改变progressBar和LCD的显示 
示例说明: 
L22~30:

self.controlsGroup = QGroupBox("运行样本")
self.lcdNumber = QLCDNumber(self)
self.slider = Qslider(Qt.Horizontal, self)
self.pBar = QProgressBar(self)
vbox = QVBoxLayout()
vbox.addWidget(self.pBar)
vbox.addWidget(self.lcdNumber)
vbox.addWidget(self.slider)
self.controlsGroup.setLayout(vbox)

实例化一个QGroupBox,在其中添加Qslider,QProgressBar,QLCDNumber控件。

L32~41:

        controlsLayout = QGridLayout()
        self.label1 = Qlabel("保存状态:")

        …..

        Self.buttonDisconnect = QPushButton("解除关联")
        self.buttonConnect = QPushButton("绑定关联")

实例化,界面中右半部分的控件。

L58~65:

self.buttonRun.clicked.connect(self.buttonSave.clicked)
self.slider.valueChanged.connect(self.pBar.setValue)
self.slider.valueChanged.connect(self.lcdNumber.display)
self.buttonSave.clicked.connect(self.showMessage)
self.buttonRun.clicked.connect(self.showMessage)
self.buttonDisconnect.clicked.connect(self.unbindConnection)
self.buttonConnect.clicked.connect(self.bindConnection)
self.buttonStop.clicked.connect(self.stop)

signal和slot进行绑定。 
1、一个信号绑定多个槽: 
self.slider.valueChanged.connect(self.pBar.setValue) self.slider.valueChanged.connect(self.lcdNumber.display) 
slider控件的valueChanged信号,同时与QProgressBar的setValue(),QLCDNumber的display()槽函数绑定,当valueChanged信号触发的时候,这两个槽函数均会被调用。

2、多个信号绑定到一个槽: 
self.buttonSave.clicked.connect(self.showMessage) 
self.buttonRun.clicked.connect(self.showMessage)

buttonSave和buttonRun这两个对象的clicked信号,同时绑定到showMessage()这个槽函数。无论哪一个信号被触发,showMessage()这个槽函数均会被调用。

3、信号和槽的连接可以被移除: 
self.buttonDisconnect.clicked.connect(self.unbindConnection)

当buttonDisconnect信号触发之后,与其关联的槽函数unbindConnection()中就会执行disconnect()方法,如下:

    def unbindConnection(self):
        self.slider.valueChanged.disconnect()

其中执行disconnect()的时候可以指定解除与某个特定的slot槽的关联,比如self.slider.valueChanged.disconnect(self.pBar.setValue),此时解除和QProgressBar的setValue()的关联;或者不指定,在不指定slot的场景下这样将解除和这个信号所有关联的槽。

4、信号与信号的关联: 
self.buttonRun.clicked.connect(self.buttonSave.clicked) 
在示例说明中提到,在运行之前要对样本进行保存,所以为了保证运行的时候执行了保存的操作,所以将buttonRun.clicked信号和buttonSave.clicked信号关联起来。

示例中在没有执行“保存”(buttonSave)的时候,执行“运行”(buttonRun),此时由于两个对象的clicked信号已经关联,所以buttonSave的clicked同样会执行。


关于信号的参数使用python类型的特点,在后面自定义信号中会进行说明。

Tips
郴维网为您提供各类专业服务:
软件开发,电脑配件销售,WIFI路由器销售,上门电脑维修,上门安装系统,系统安装,软、硬件安装,电脑除尘清灰,显示器维修,WIFI安装调试,服务器维护,数据恢复,密码破解,网络布线,网络检修,打印机维修,打印机加碳粉,苹果电脑安装系统,苹果电脑安装双系统,监控安装维护,电脑外包,笔记本电脑维修,餐饮、美容行业软件安装 等。。。。。。
点击次数:1364 更新时间:2018-4-3 12:54:47  【打印此页
关键词推荐:郴州电脑城 郴州电脑维修公司 维修电脑公司 郴州软件开发 上门电脑维修 上门安装系统 笔记本电脑维修 郴州打印机维修 打印机加碳粉 电脑安装双系统 苹果电脑双系统 液晶显示器维修 联想笔记本维修 联想笔记本维修电话 戴尔笔记本维修电话 郴州戴尔笔记本维修 戴尔笔记本郴州维修点 华硕笔记本维修点 郴州华硕笔记本维修 郴州笔记本上网维修