PyQt GUI程式設計——訊號與槽
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!