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!