概述
信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。
信号和槽是用来在对象间传递数据的方法:当一个特定事件发生的时候,信号会被发射出来,槽调用是用来响应相应的信号的。Qt中对象已经包含了许多预定义的信号(基本组件都有各自特有的预定义的信号),根据使用的场景也可以添加新的信号。同样Qt的对象中已经包含了许多预定义的槽函数,但也可以根据使用的场景添加新的槽函数。
一、概念简介
所有继承qwidget的控件都支持信号与槽机制。
信号:当一个信号发生改变时,向外界发出的信息。
当一个信号被发射的时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。
如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。
槽:一个执行某些操作的函数或者方法。
当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。
信号与槽机制:主要分两种
手动操作:信号连接槽
自动操作:当信号发出时,连续的槽函数会自动执行
信号连接
通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:
object.信号.connet(槽函数)
当信号与槽没有必要继续保持关联时,可以使用 disconnect 函数来断开连接。其定义如下:
disconnect(槽函数)
信号和槽的特点:
1.一个信号可以连接到多个槽:当信号发出后,槽函数都会被调用,但是调用的顺序是随机的,不确定的。
2.多个信号可以连接到同一个槽:其中任何一个信号发出,槽函数都会被执行。
3.信号的参数可以是任何的Python类型,如list,dict等python独有的类型。自定义信号的时候举例说明。
4.信号和槽的连接可以被移除:比如断开某个特定信号的关联。
5.信号可以和另外一个信号进行关联:第一个信号发出后,第二个信号也同时发送。比如关闭系统的信号发出之后,同时会发出保存数据的信号。
二、代码样例
整体代码如下:
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_())
控件说明:
控件类型 | 控件名称 | 作用 |
---|---|---|
controlsGroup | QGroupBox | 为构建分组框提供了支持。分组框通常带有一个边框和一个标题栏,作为容器部件来使用,在其中可以布置各种窗口部件。 |
lcdNumber | QLCDNumber | 用于显示一个带有类似液晶显示屏效果的数字。 |
slider | QSlider | 提供一个垂直或者水平的滑动条,滑动条是一个用于控制有界值典型的控件,它允许用户沿水平或者垂直方向在某一范围内移动滑块,并将滑块所在的位置转换为一个合法范围内的整数值 |
pBar | QProgressBar | 提供了一个水平或垂直的进度条 |
label1 | QLabel |
|
buttonSave | QPushButton | 常用的按钮控件 |
界面说明:
程序样本运行的界面逻辑,先设定运行的程序样本数量,然后先保存后运行的逻辑状态。通过slider的滑动来改变progressBar和LCD的显示数据;“保存”按钮保存运行的样本;“运行”按钮运行程序样本;“解除关联”解除slider.valueChanged信号的绑定,此时slider的滑动,不会改变progressBar和LCD的显示。
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,在其中添加QProgressBar、QLCDNumber、QSlider控件。
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)
通过QGridLayout()添加标签以及按钮。
layout = QHBoxLayout()
layout.addWidget(self.controlsGroup)
layout.addLayout(controlsLayout)
self.setLayout(layout)
最后通过QHBoxLayout将左右两个界面合并,形成最终界面。
信号与槽说明:
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()这个槽函数均会被调用,而根据self.sender().text() 这个函数来判断显示的不同内容。
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()的关联,如果不指定,将解除和这个信号所有关联的槽。
4、信号与信号的关联:
self.buttonRun.clicked.connect(self.buttonSave.clicked)
在样例说明中提到,在运行之前要对样本进行保存,所以为了保证运行的时候执行了保存的操作,所以将buttonRun.clicked信号和buttonSave.clicked信号关联起来。
示例中在没有执行“保存”(buttonSave)的时候,执行“运行”(buttonRun),此时由于两个对象的clicked信号已经关联,所以buttonSave的clicked同样会执行。
最终结果:
本文是《从零开始学PyQt5》第五篇,希望小伙伴们可以多多支持,一起学习!
参考:
Pyqt5系列(七)-信号与槽机制_追逐阳光的风-CSDN博客_pyqt5信号和槽
最后
以上就是陶醉雨为你收集整理的PyQt5(五)信号与槽机制一、概念简介二、代码样例的全部内容,希望文章能够帮你解决PyQt5(五)信号与槽机制一、概念简介二、代码样例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复