信号:
当对象的状态发生改变的时候,信号就由该对象发射 (emit) 出去。当一个信号被发射(emit)时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。
如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。
槽:
用于接受信号,而且槽只是普通的对象成员函数。当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。
信号和槽的绑定:
通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:
connect(slot[, type=PyQt5.QtCore.Qt.AutoConnection[, no_receiver_check=False]])
# self.部件信号.事件.connect(需要连接的槽函数)
当信号与槽没有必要继续保持关联时,我们可以使用 disconnect 函数来断开连接。其定义如下:
disconnect([slot])
信号和槽的特点:
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.disconnect()
5、信号可以和另外一个信号进行关联;
第一个信号发出后,第二个信号也同时发送。比如关闭系统的信号发出之后,同时会发出保存数据的信号。
代码示例:
关于信号和槽的式样代码如下:
#-*- coding:utf-8 -*-
'''
Signal & Slot
'''
__author__ = 'Tony Zhu'
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的显示 。