PyQt中使用信号与槽的机制实现对象之间的通信。
信号
当对象改变其状态时,信号就由该对象发射出去,并且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。
槽
用于接收信号,并且槽只是普通的对象成员函数。一个槽并不知道是否有其他信号自己相连接,而且对象并不了解具体的通信机制。
信号和槽的绑定
通过调用QObject对象的connect()函数将某个对象的信号与另外一个对象的槽函数相关联。这样当发射者发射信号时,接受者的槽函数将被调用。
一个信号可以连接到多个槽,当信号发出后,槽函数都会被调用,但是调用的顺序是随机的,不确定的。
多个信号可以连接到同一个槽,其中任何一个信号发出,槽函数都会被执行。
信号和槽的连接可以被移除,PyQt5提供了disconnect()成员函数来进行解绑。
信号可以和另外一个信号进行关联;第一个信号发出后,第二个信号也同时发送。
一个演示信号和槽的关系的样例
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class SignalSlot(QWidget):
def __init__(self):
super(SignalSlot, self).__init__()
self.initUI()
def initUI(self):
self.controlsGroup = QGroupBox('信号和槽')
self.lcdNumber = QLCDNumber(self) # 创建lcdNumber控件
self.slider = QSlider(Qt.Horizontal, self) # 创建slider控件
self.pBar = QProgressBar(self) # 创建ProgressBar控件
vbox = QVBoxLayout() # 创建垂直布局
vbox.addWidget(self.pBar) # 将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) # 在网格布局中1行1列添加控件
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.slider.valueChanged.connect(self.pBar.setValue)
self.slider.valueChanged.connect(self.lcdNumber.display)
self.buttonRun.clicked.connect(self.buttonSave.clicked)
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_())
-------------------------------------------------------------代码分割线--------------------------------------------
1-47行生成用户界面
47-54行连接了信号与槽。
self.slider.valueChanged.connect(self.pBar.setValue)
连接滑动条的改变(信号) 到进度条显示(槽)
self.slider.valueChanged.connect(self.lcdNumber.display)
连接滑动条的改变(信号) 到LCD面板显示(槽)
self.buttonRun.clicked.connect(self.buttonSave.clicked)
连接运行按钮点击操作(信号) 到保存按钮点击操作(信号)
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)
连接停止按钮点击操作(信号)到停止操作(槽)
66-67行解除了信号和槽的关联
def unbindConnection(self): self.slider.valueChanged.disconnect()
解除滑动条的改变(信号)的一切关联。
--------------------------------------------------------------------------------------
本文实例来源:《Python程序设计》人民邮电出版社 王学军 胡畅霞 韩艳峰 主编
That's All .Thankyou!