PyQt5信號與槽機制案例詳解
信號和槽機制是 QT 的核心機制,要精通 QT 編程就必須對信號和槽有所了解。信號和槽是一種高級接口,應用于對象之間的通信,它是 QT 的核心特性,也是 QT 區(qū)別于其它工具包的重要地方。
信號和槽是用來在對象間傳遞數據的方法:當一個特定事件發(fā)生的時候,信號會被發(fā)射出來,槽調用是用來響應相應的信號的。Qt中對象已經包含了許多預定義的信號(基本組件都有各自特有的預定義的信號),根據使用的場景也可以添加新的信號。同樣Qt的對象中已經包含了許多預定義的槽函數,但也可以根據使用的場景添加新的槽函數。
一、概念簡介
所有繼承qwidget的控件都支持信號與槽機制。
信號:當一個信號發(fā)生改變時,向外界發(fā)出的信息。
當一個信號被發(fā)射的時候,與其關聯的槽函數被立刻執(zhí)行。其中該對象只負責發(fā)送信號,發(fā)射該信號的對象并不知道是那個對象在接收這個信號。這樣保證了對象與對象之間的低耦合。
如果存在信號和多個槽函數相關聯的時候,當信號被發(fā)射時,這些槽的執(zhí)行順序將會是隨機的、不確定的。
槽:一個執(zhí)行某些操作的函數或者方法。
當和槽連接的信號被發(fā)射時,槽會被調用。一個槽并不知道是否有任何信號與自己相連接。
信號與槽機制:主要分兩種
手動操作:信號連接槽
自動操作:當信號發(fā)出時,連續(xù)的槽函數會自動執(zhí)行
信號連接
通過調用 QObject 對象的 connect 函數來將某個對象的信號與另外一個對象的槽函數相關聯,這樣當發(fā)射者發(fā)射信號時,接收者的槽函數將被調用。該函數的定義如下:
object.信號.connet(槽函數)
當信號與槽沒有必要繼續(xù)保持關聯時,可以使用 disconnect 函數來斷開連接。其定義如下:
disconnect(槽函數)
信號和槽的特點:
1.一個信號可以連接到多個槽:當信號發(fā)出后,槽函數都會被調用,但是調用的順序是隨機的,不確定的。
2.多個信號可以連接到同一個槽:其中任何一個信號發(fā)出,槽函數都會被執(zhí)行。
3.信號的參數可以是任何的Python類型,如list,dict等python獨有的類型。自定義信號的時候舉例說明。
4.信號和槽的連接可以被移除:比如斷開某個特定信號的關聯。
5.信號可以和另外一個信號進行關聯:第一個信號發(fā)出后,第二個信號也同時發(fā)送。比如關閉系統的信號發(fā)出之后,同時會發(fā)出保存數據的信號。
二、代碼樣例
整體代碼如下:
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("保存狀態(tài):") self.saveLabel = QLabel() self.label2 = QLabel("運行狀態(tài):") 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.runLabel.setText("Running") def unbindConnection(self): self.slider.valueChanged.disconnect() def bindConnection(self): 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 | 常用的按鈕控件 |
界面說明:
程序樣本運行的界面邏輯,先設定運行的程序樣本數量,然后先保存后運行的邏輯狀態(tài)。通過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("保存狀態(tài):") self.saveLabel = QLabel() self.label2 = QLabel("運行狀態(tài):") 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信號觸發(fā)的時候,這兩個槽函數均會被調用。
2.多個信號綁定到一個槽:
self.buttonSave.clicked.connect(self.showMessage) self.buttonRun.clicked.connect(self.showMessage)
buttonSave和buttonRun這兩個對象的clicked信號,同時綁定到showMessage()這個槽函數。無論哪一個信號被觸發(fā),showMessage()這個槽函數均會被調用,而根據self.sender().text() 這個函數來判斷顯示的不同內容。
3.信號和槽的連接可以被移除:
self.buttonDisconnect.clicked.connect(self.unbindConnection)
當buttonDisconnect信號觸發(fā)之后,與其關聯的槽函數unbindConnection()中就會執(zhí)行disconnect()方法,如下:
def unbindConnection(self): self.slider.valueChanged.disconnect()
其中執(zhí)行disconnect()的時候可以指定解除與某個特定的slot槽的關聯,比如self.slider.valueChanged.disconnect(self.pBar.setValue),此時解除和QProgressBar的setValue()的關聯,如果不指定,將解除和這個信號所有關聯的槽。
4、信號與信號的關聯:
self.buttonRun.clicked.connect(self.buttonSave.clicked)
在樣例說明中提到,在運行之前要對樣本進行保存,所以為了保證運行的時候執(zhí)行了保存的操作,所以將buttonRun.clicked信號和buttonSave.clicked信號關聯起來。
示例中在沒有執(zhí)行“保存”(buttonSave)的時候,執(zhí)行“運行”(buttonRun),此時由于兩個對象的clicked信號已經關聯,所以buttonSave的clicked同樣會執(zhí)行。
最終結果:
本文是《從零開始學PyQt5》第五篇,希望小伙伴們可以多多支持,一起學習!
參考:
Pyqt5系列(七)-信號與槽機制_追逐陽光的風-CSDN博客_pyqt5信號和槽
到此這篇關于PyQt5信號與槽機制案例詳解的文章就介紹到這了,更多相關PyQt5信號與槽機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python smtplib模塊自動收發(fā)郵件功能(一)
這篇文章主要為大家詳細介紹了python smtplib模塊自動收發(fā)郵件功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05