首頁 > 軟體

Python PyQt5學習之自定義訊號

2022-03-02 13:01:11

PyQ5已經自動定義了很多QT自建的訊號。但是在實際的使用中為了靈活使用訊號與槽機制,可以根據需要自定義訊號。通過使用pyqtSignal()方法定義新的訊號,新的訊號作為類的屬性。

自定義signal說明:

新的訊號應該定義在QObject的子類中。新的訊號必須作為定義類的一部分,不允許將訊號作為類的屬性在類定義之後通過動態的方式進行新增。通過這種方式新的訊號才能自動的新增到QMetaObject類中。這就意味這新定義的訊號將會出現在Qt Designer,並且可以通過QMetaObject API實現內省。

自定義訊號的發射,通過emit()方法類實現

自定義訊號的一般流程如下:

  1. 定義訊號
  2. 定義槽函數
  3. 繫結訊號和槽
  4. 發射訊號

程式碼範例

import sys
from PyQt5.QtCore import pyqtSignal, QObject, Qt, pyqtSlot
from PyQt5.QtWidgets import QWidget, QApplication, QGroupBox, QPushButton, QLabel, QCheckBox, QSpinBox, QHBoxLayout, QComboBox, QGridLayout
 
 
class SignalEmit(QWidget):
    helpSignal = pyqtSignal(str)
    printSignal = pyqtSignal(list)
    #宣告一個多過載版本的訊號,包括了一個帶int和str型別引數的訊號,以及帶str引數的訊號
    previewSignal = pyqtSignal([int,str],[str])
    def __init__(self):
        super().__init__()        
        self.initUI()
 
 
    def initUI(self):           
 
        self.creatContorls("列印控制:")
        self.creatResult("操作結果:")
 
        layout = QHBoxLayout()
        layout.addWidget(self.controlsGroup)
        layout.addWidget(self.resultGroup)
        self.setLayout(layout)
 
        self.helpSignal.connect(self.showHelpMessage)
        self.printSignal.connect(self.printPaper)
        self.previewSignal[str].connect(self.previewPaper)
        self.previewSignal[int,str].connect(self.previewPaperWithArgs)  
        self.printButton.clicked.connect(self.emitPrintSignal)
        self.previewButton.clicked.connect(self.emitPreviewSignal)
 
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('defined signal')
        self.show()
 
    def creatContorls(self,title):
        self.controlsGroup = QGroupBox(title)
        self.printButton = QPushButton("列印")
        self.previewButton  = QPushButton("預覽")
        numberLabel = QLabel("列印份數:")
        pageLabel = QLabel("紙張型別:")
        self.previewStatus = QCheckBox("全螢幕預覽")
        self.numberSpinBox = QSpinBox()
        self.numberSpinBox.setRange(1, 100)
        self.styleCombo = QComboBox(self)
        self.styleCombo.addItem("A4")
        self.styleCombo.addItem("A5")
 
        controlsLayout = QGridLayout()
        controlsLayout.addWidget(numberLabel, 0, 0)
        controlsLayout.addWidget(self.numberSpinBox, 0, 1)
        controlsLayout.addWidget(pageLabel, 0, 2)
        controlsLayout.addWidget(self.styleCombo, 0, 3)
        controlsLayout.addWidget(self.printButton, 0, 4)
        controlsLayout.addWidget(self.previewStatus, 3, 0)
        controlsLayout.addWidget(self.previewButton, 3, 1)
        self.controlsGroup.setLayout(controlsLayout)
 
    def creatResult(self,title):
        self.resultGroup = QGroupBox(title)
        self.resultLabel = QLabel("")
        layout = QHBoxLayout()
        layout.addWidget(self.resultLabel)
        self.resultGroup.setLayout(layout)
 
    def emitPreviewSignal(self):
        if self.previewStatus.isChecked() == True:
            self.previewSignal[int,str].emit(1080," Full Screen")
        elif self.previewStatus.isChecked() == False:
            self.previewSignal[str].emit("Preview")
 
    def emitPrintSignal(self):
        pList = []
        pList.append(self.numberSpinBox.value ())
        pList.append(self.styleCombo.currentText())
        self.printSignal.emit(pList)
 
    def printPaper(self,list):
        self.resultLabel.setText("Print: "+"份數:"+ str(list[0]) +"  紙張:"+str(list[1]))
 
    def previewPaperWithArgs(self,style,text):
        self.resultLabel.setText(str(style)+text)
 
    def previewPaper(self,text):
        self.resultLabel.setText(text)          
 
    def keyPressEvent(self, event):
 
        if event.key() == Qt.Key_F1:
            self.helpSignal.emit("help message")
 
    def showHelpMessage(self,message):
        self.resultLabel.setText(message)
        #self.statusBar().showMessage(message)
 
 
if __name__ == '__main__':
 
    app = QApplication(sys.argv)
    dispatch = SignalEmit()
    sys.exit(app.exec_())

樣例說明:

通過一個模擬列印的介面來詳細說明一下關於訊號的自定義,在列印的時候可以設定列印的分數,紙張型別,觸發“列印”按鈕之後,將執行結果顯示到右側;通過全螢幕預覽QCheckBox來選擇是否通過全螢幕模式進行預覽,將執行結果顯示到右側。

通過點選F1快捷鍵,可以顯示helpMessage資訊。

介面分析:

該介面主要由兩個部分組成:一個是列印控制,另一個是操作結果。

通過QHBoxLayout組合起來,如下所示:

layout = QHBoxLayout()
layout.addWidget(self.controlsGroup)
layout.addWidget(self.resultGroup)
self.setLayout(layout)

然後通過creatContorls定義“列印控制”介面,

def creatContorls(self,title):
    self.controlsGroup = QGroupBox(title)
    self.printButton = QPushButton("列印")
    self.previewButton  = QPushButton("預覽")
    numberLabel = QLabel("列印份數:")
    pageLabel = QLabel("紙張型別:")
    self.previewStatus = QCheckBox("全螢幕預覽")
    self.numberSpinBox = QSpinBox()
    self.numberSpinBox.setRange(1, 100)
    self.styleCombo = QComboBox(self)
    self.styleCombo.addItem("A4")
    self.styleCombo.addItem("A5")
 
    controlsLayout = QGridLayout()
    controlsLayout.addWidget(numberLabel, 0, 0)
    controlsLayout.addWidget(self.numberSpinBox, 0, 1)
    controlsLayout.addWidget(pageLabel, 0, 2)
    controlsLayout.addWidget(self.styleCombo, 0, 3)
    controlsLayout.addWidget(self.printButton, 0, 4)
    controlsLayout.addWidget(self.previewStatus, 3, 0)
    controlsLayout.addWidget(self.previewButton, 3, 1)
    self.controlsGroup.setLayout(controlsLayout)

QSpinBox是一個計數器控制元件,允許使用者選擇一個整數值通過單擊向上向下或者按鍵盤上的上下鍵來增加減少當前顯示的值,當然使用者也可以輸入值。

QComboBox是一個集按鈕和下拉選項於一體的控制元件,也稱做下拉選單框。

 然後通過creatResult定義“操作結果”介面:

def creatResult(self,title):
        self.resultGroup = QGroupBox(title)
        self.resultLabel = QLabel("")
        layout = QHBoxLayout()
        layout.addWidget(self.resultLabel)
        self.resultGroup.setLayout(layout)

程式碼分析:

helpSignal = pyqtSignal(str)
printSignal = pyqtSignal(list)
#宣告一個多過載版本的訊號,包括了一個帶int和str型別引數的訊號,以及帶str引數的訊號
previewSignal = pyqtSignal([int,str],[str])

通過pyqtSignal()定義了三個訊號,helpSignal,printSignal,previewSignal。其中:

  • helpSignal 為str引數型別的訊號。
  • printSignal 為list引數型別的訊號。
  • previewSignal為一個多過載版本的訊號,包括了一個帶int和str型別引數的訊號,以及str類行的引數。
self.helpSignal.connect(self.showHelpMessage)
self.printSignal.connect(self.printPaper)
self.previewSignal[str].connect(self.previewPaper)
self.previewSignal[int,str].connect(self.previewPaperWithArgs)  
self.printButton.clicked.connect(self.emitPrintSignal)
self.previewButton.clicked.connect(self.emitPreviewSignal)

繫結訊號和槽。

著重說明一下多過載版本的訊號的繫結,previewSignal有兩個版本previewSignal(str),previewSignal(int,str)。由於存在兩個版本,從因此在繫結的時候需要顯式的指定訊號和槽的繫結關係。

具體如下:

self.previewSignal[str].connect(self.previewPaper) self.previewSignal[int,str].connect(self.previewPaperWithArgs)

其中[str]引數的previewSignal訊號繫結previewPaper();[int,str]的previewSignal訊號繫結previewPaperWithArgs()

def emitPreviewSignal(self):
        if self.previewStatus.isChecked() == True:
            self.previewSignal[int,str].emit(1080," Full Screen")
        elif self.previewStatus.isChecked() == False:
            self.previewSignal[str].emit("Preview")

多過載版本的訊號的發射也需要制定對應發射的版本,類似同訊號的版定。

def emitPrintSignal(self):
        pList = []
        pList.append(self.numberSpinBox.value ())
        pList.append(self.styleCombo.currentText())
        self.printSignal.emit(pList)

如程式碼中所示,在訊號發射的時候可以傳遞python資料型別的引數,在本例中傳遞list型別的引數pList。

def keyPressEvent(self, event):
    if event.key() == Qt.Key_F1:
         self.helpSignal.emit("help message")

通過複寫keyPressEvent()方法,將F1快捷鍵進行功能的拓展。在windows的大部分應用,我們都會使用一些快捷鍵來快速的完成某些特定的功能。比如F1鍵,會快速調出幫助介面,那就可以複寫keyPressEvent()方法來模擬傳送所需的訊號,來完成對應任務。

注意事項:

1.自定義的訊號在init()函數之前定義

2.自定義型號可以傳遞,str、int、list、object、float、tuple、dict等很多型別的引數

3.注意signal和slot的呼叫邏輯,避免signal和slot之間出現死迴圈。如在slot方法中繼續發射該訊號

到此這篇關於Python PyQt5學習之自定義訊號的文章就介紹到這了,更多相關Python PyQt5訊號內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com