python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5信號(hào)與槽機(jī)制、自定義信號(hào)基礎(chǔ)介紹
信號(hào)和槽機(jī)制是 QT 的核心機(jī)制,要精通 QT 編程就必須對(duì)信號(hào)和槽有所了解。信號(hào)和槽是一種高級(jí)接口,應(yīng)用于對(duì)象之間的通信,它是 QT 的核心特性,也是 QT 區(qū)別于其它工具包的重要地方。
在linux、windows等 GUI 工具包中,GUI組件都會(huì)注冊(cè)回調(diào)函數(shù)用于處理組件所觸發(fā)的動(dòng)作,通常是注冊(cè)對(duì)應(yīng)的函數(shù)的函數(shù)指針。在之前關(guān)于Button的文章中提到了信號(hào)與槽的機(jī)制的使用,通過(guò)該機(jī)制可以很好的將組件的信號(hào)(如button的clocked、toggled、pressed等)和處理該信號(hào)的槽關(guān)聯(lián)起來(lái)。通過(guò) 信號(hào)與槽機(jī)制,能夠讓我們很簡(jiǎn)潔和快速的來(lái)完成相關(guān)的功能。
信號(hào)和槽是用來(lái)在對(duì)象間傳遞數(shù)據(jù)的方法:當(dāng)一個(gè)特定事件發(fā)生的時(shí)候,signal會(huì)被emit出來(lái),slot調(diào)用是用來(lái)響應(yīng)相應(yīng)的signal的。Qt中對(duì)象已經(jīng)包含了許多預(yù)定義的 signal(基本組件都有各自特有的預(yù)定義的信號(hào)),根據(jù)使用的場(chǎng)景我們可以添加新的signal。Qt的對(duì)象中已經(jīng)包含了許多預(yù)定義的槽函數(shù),但我們也根據(jù)使用的場(chǎng)景添加新的槽函數(shù)。
信號(hào)當(dāng)對(duì)象的狀態(tài)發(fā)生改變的時(shí)候,信號(hào)就由該對(duì)象發(fā)射 (emit) 出去。當(dāng)一個(gè)信號(hào)被發(fā)射(emit)時(shí)候,與其關(guān)聯(lián)的槽函數(shù)被立刻執(zhí)行。其中該對(duì)象只負(fù)責(zé)發(fā)送信號(hào),發(fā)射該信號(hào)的對(duì)象并不知道是那個(gè)對(duì)象在接收這個(gè)信號(hào)。這樣保證了對(duì)象與對(duì)象之間的低耦合。
如果存在信號(hào)和多個(gè)槽函數(shù)相關(guān)聯(lián)的時(shí)候,當(dāng)信號(hào)被發(fā)射時(shí),這些槽的執(zhí)行順序?qū)?huì)是隨機(jī)的、不確定的。
槽用于接受信號(hào),而且槽只是普通的對(duì)象成員函數(shù)。當(dāng)和槽連接的信號(hào)被發(fā)射時(shí),槽會(huì)被調(diào)用。一個(gè)槽并不知道是否有任何信號(hào)與自己相連接。
信號(hào)和槽的綁定通過(guò)調(diào)用 QObject 對(duì)象的 connect 函數(shù)來(lái)將某個(gè)對(duì)象的信號(hào)與另外一個(gè)對(duì)象的槽函數(shù)相關(guān)聯(lián),這樣當(dāng)發(fā)射者發(fā)射信號(hào)時(shí),接收者的槽函數(shù)將被調(diào)用。該函數(shù)的定義如下::
connect(slot[, type=PyQt5.QtCore.Qt.AutoConnection[, no_receiver_check=False]])
Parameters:
slot ? the slot to connect to, either a Python callable or another bound signal.
type ? the type of the connection to make.
no_receiver_check ? suppress the check that the underlying C++ receiver instance still exists and deliver the signal anyway.
當(dāng)信號(hào)與槽沒(méi)有必要繼續(xù)保持關(guān)聯(lián)時(shí),我們可以使用 disconnect 函數(shù)來(lái)斷開(kāi)連接。其定義如下:
disconnect([slot])
Parameters: slot ? the optional slot to disconnect from, either a Python callable or another bound signal. If it is omitted then all slots connected to the signal are disconnected.
信號(hào)和槽的特點(diǎn)1、一個(gè)信號(hào)可以連接到多個(gè)槽;當(dāng)信號(hào)發(fā)出后,槽函數(shù)都會(huì)被調(diào)用,但是調(diào)用的順序是隨機(jī)的,不確定的。
self.slider.valueChanged.connect(self.pBar.setValue)
self.slider.valueChanged.connect(self.lcdNumber.display)
QSlider數(shù)據(jù)的變化同時(shí)綁定在setValue()和display()兩個(gè)槽上。
2、多個(gè)信號(hào)可以連接到同一個(gè)槽;其中任何一個(gè)信號(hào)發(fā)出,槽函數(shù)都會(huì)被執(zhí)行。
self.buttonOn.clicked.connect(self.showMessage)
self.buttonOff.clicked.connect(self.showMessage)
showMessage()同時(shí)綁定在兩個(gè)button的clicked信號(hào)上
3、信號(hào)的參數(shù)可以是任何的Python類(lèi)型;如list,dict等python獨(dú)有的類(lèi)型。自定義信號(hào)的時(shí)候舉例說(shuō)明。
4、信號(hào)和槽的連接可以被移除;比如斷開(kāi)某個(gè)特定信號(hào)的關(guān)聯(lián)。
self.buttonOn.clicked.connect(self.showMessage)
5、信號(hào)可以和另外一個(gè)信號(hào)進(jìn)行關(guān)聯(lián);第一個(gè)信號(hào)發(fā)出后,第二個(gè)信號(hào)也同時(shí)發(fā)送。比如關(guān)閉系統(tǒng)的信號(hào)發(fā)出之后,同時(shí)會(huì)發(fā)出保存數(shù)據(jù)的信號(hào)。
代碼示例:
關(guān)于信號(hào)和槽的式樣代碼如下:
#-*- coding:utf-8 -*-’’’Signal & Slot’’’__author__ = ’Tony Zhu’import sysfrom PyQt5.QtCore import Qtfrom 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('運(yùn)行樣本') 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('運(yùn)行狀態(tài):') self.runLabel = QLabel() self.buttonSave = QPushButton('保存') self.buttonRun = QPushButton('運(yùn)行') self.buttonStop = QPushButton('停止') self.buttonDisconnect = QPushButton('解除關(guān)聯(lián)') self.buttonConnect = QPushButton('綁定關(guān)聯(lián)') 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(’信號(hào)和槽’) def showMessage(self): if self.sender().text() == '保存': self.saveLabel.setText('Saved') elif self.sender().text() == '運(yùn)行': 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_())
程序運(yùn)行的結(jié)果:
控件說(shuō)明:
控件類(lèi)型 控件名稱(chēng) 作用 QLCDNumber lcdNumber 顯示slider滑動(dòng)之后的數(shù)據(jù) QProgressBar pBar 顯示slider滑動(dòng)之后的數(shù)據(jù)(百分比數(shù)據(jù)) QSlider slider 滑動(dòng)塊調(diào)整數(shù)據(jù) QPushButton buttonSave 在saveLabel顯示保存的狀態(tài)”Saved” QPushButton buttonRun 在runLabel顯示運(yùn)行的狀態(tài)”Running” QPushButton buttonDisconnect 解除slider.valueChanged信號(hào)的綁定 QPushButton buttonConnect 連接slider.valueChanged信號(hào)的綁定 QPushButton buttonStop 清除saveLabel和runLabel的信息示例說(shuō)明:
程序樣本運(yùn)行的界面邏輯,先設(shè)定運(yùn)行的程序樣本數(shù)量,然后先保存后運(yùn)行的邏輯狀態(tài)。通過(guò)slider的滑動(dòng)來(lái)改變progressBar和LCD的顯示數(shù)據(jù);“保存”按鈕保存運(yùn)行的樣本;“運(yùn)行”按鈕運(yùn)行程序樣本;“解除關(guān)聯(lián)”解除slider.valueChanged信號(hào)的綁定,此時(shí)slider的滑動(dòng),不會(huì)改變progressBar和LCD的顯示
示例說(shuō)明:
L22~30:
self.controlsGroup = QGroupBox('運(yùn)行樣本')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)
實(shí)例化一個(gè)QGroupBox,在其中添加QSlider,QProgressBar,QLCDNumber控件。
L32~41:
controlsLayout = QGridLayout()self.label1 = QLabel('保存狀態(tài):').....self.buttonDisconnect = QPushButton('解除關(guān)聯(lián)')self.buttonConnect = QPushButton('綁定關(guān)聯(lián)')
實(shí)例化,界面中右半部分的控件。
L58~65:
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)signal和slot進(jìn)行綁定。1、一個(gè)信號(hào)綁定多個(gè)槽:
self.slider.valueChanged.connect(self.pBar.setValue)
self.slider.valueChanged.connect(self.lcdNumber.display)
slider控件的valueChanged信號(hào),同時(shí)與QProgressBar的setValue(),QLCDNumber的display()槽函數(shù)綁定,當(dāng)valueChanged信號(hào)觸發(fā)的時(shí)候,這兩個(gè)槽函數(shù)均會(huì)被調(diào)用。
2、多個(gè)信號(hào)綁定到一個(gè)槽:self.buttonSave.clicked.connect(self.showMessage)
self.buttonRun.clicked.connect(self.showMessage)
buttonSave和buttonRun這兩個(gè)對(duì)象的clicked信號(hào),同時(shí)綁定到showMessage()這個(gè)槽函數(shù)。無(wú)論哪一個(gè)信號(hào)被觸發(fā),showMessage()這個(gè)槽函數(shù)均會(huì)被調(diào)用。
3、信號(hào)和槽的連接可以被移除:self.buttonDisconnect.clicked.connect(self.unbindConnection)
當(dāng)buttonDisconnect信號(hào)觸發(fā)之后,與其關(guān)聯(lián)的槽函數(shù)unbindConnection()中就會(huì)執(zhí)行disconnect()方法,如下:
def unbindConnection(self):self.slider.valueChanged.disconnect()
其中執(zhí)行disconnect()的時(shí)候可以指定解除與某個(gè)特定的slot槽的關(guān)聯(lián),比如self.slider.valueChanged.disconnect(self.pBar.setValue),此時(shí)解除和QProgressBar的setValue()的關(guān)聯(lián);或者不指定,在不指定slot的場(chǎng)景下這樣將解除和這個(gè)信號(hào)所有關(guān)聯(lián)的槽。
4、信號(hào)與信號(hào)的關(guān)聯(lián):self.buttonRun.clicked.connect(self.buttonSave.clicked)
在示例說(shuō)明中提到,在運(yùn)行之前要對(duì)樣本進(jìn)行保存,所以為了保證運(yùn)行的時(shí)候執(zhí)行了保存的操作,所以將buttonRun.clicked信號(hào)和buttonSave.clicked信號(hào)關(guān)聯(lián)起來(lái)。
示例中在沒(méi)有執(zhí)行“保存”(buttonSave)的時(shí)候,執(zhí)行“運(yùn)行”(buttonRun),此時(shí)由于兩個(gè)對(duì)象的clicked信號(hào)已經(jīng)關(guān)聯(lián),所以buttonSave的clicked同樣會(huì)執(zhí)行。
PyQt5自定義信號(hào)PyQt5已經(jīng)自動(dòng)定義了很多QT內(nèi)建的信號(hào)。但是在實(shí)際的使用中為了靈活使用信號(hào)與槽機(jī)制,我們可以根據(jù)需要自定義signal。可以使用pyqtSignal()方法定義新的信號(hào),新的信號(hào)作為類(lèi)的屬性。
自定義signal說(shuō)明:pyqtSignal()方法原型(PyQt官網(wǎng)的定義):
PyQt5.QtCore.pyqtSignal(types[, name[, revision=0[, arguments=[]]]])
Create one or more overloaded unbound signals as a class attribute.
Parameters:
types ? the types that define the C++ signature of the signal. Each type may be a Python type object or a string that is the name of a C++ type. Alternatively each may be a sequence of type arguments. In this case each sequence defines the signature of a different signal overload. The first overload will be the default.
name ? the name of the signal. If it is omitted then the name of the class attribute is used. This may only be given as a keyword argument.
revision ? the revision of the signal that is exported to QML. This may only be given as a keyword argument.
arguments ? the sequence of the names of the signal’s arguments that is exported to QML. This may only be given as a keyword argument.
Return type: an unbound signal
新的信號(hào)應(yīng)該定義在QObject的子類(lèi)中。新的信號(hào)必須作為定義類(lèi)的一部分,不允許將信號(hào)作為類(lèi)的屬性在類(lèi)定義之后通過(guò)動(dòng)態(tài)的方式進(jìn)行添加。通過(guò)這種方式新的信號(hào)才能自動(dòng)的添加到QMetaObject類(lèi)中。這就意味這新定義的信號(hào)將會(huì)出現(xiàn)在Qt Designer,并且可以通過(guò)QMetaObject API實(shí)現(xiàn)內(nèi)省。
通過(guò)下面的例子,了解一下關(guān)于signal的定義:
from PyQt5.QtCore import QObject, pyqtSignalclass NewSignal(QObject): # 定義了一個(gè)“closed”信號(hào),該信號(hào)沒(méi)有參數(shù)據(jù) closed= pyqtSignal() # 定義了一個(gè)'range_changed'信號(hào),該信號(hào)有兩個(gè)int類(lèi)型的參數(shù) range_changed = pyqtSignal(int, int, name=’rangeChanged’)
自定義信號(hào)的發(fā)射,通過(guò)emit()方法類(lèi)實(shí)現(xiàn),具體參見(jiàn)該函數(shù)的原型:
emit(*args)
Parameters: args ? the optional sequence of arguments to pass to any connected slots.
通過(guò)下面的例子,了解一下關(guān)于emit()的使用:
from PyQt5.QtCore import QObject, pyqtSignalclass NewSignal(QObject): # 一個(gè)valueChanged的信號(hào),該信號(hào)沒(méi)有參數(shù). valueChanged = pyqtSignal() def connect_and_emit_valueChanged(self): # 綁定信號(hào)和槽函數(shù) self.valueChanged.connect(self.handle_valueChanged) # 發(fā)射信號(hào). self.trigger.emit() def handle_valueChanged(self): print('trigger signal received')
示例說(shuō)明:
自定義信號(hào)的一般流程如下:
定義信號(hào) 定義槽函數(shù) 綁定信號(hào)和槽 發(fā)射信號(hào)通過(guò)代碼示例來(lái)了解一下信號(hào)的自定義過(guò)程:
#-*- coding:utf-8 -*-’’’defined Signal’’’__author__ = ’Tony Zhu’import sysfrom PyQt5.QtCore import pyqtSignal, QObject, Qt, pyqtSlotfrom PyQt5.QtWidgets import QWidget, QApplication, QGroupBox, QPushButton, QLabel, QCheckBox, QSpinBox, QHBoxLayout, QComboBox, QGridLayoutclass SignalEmit(QWidget): helpSignal = pyqtSignal(str) printSignal = pyqtSignal(list) #聲明一個(gè)多重載版本的信號(hào),包括了一個(gè)帶int和str類(lèi)型參數(shù)的信號(hào),以及帶str參數(shù)的信號(hào) previewSignal = pyqtSignal([int,str],[str]) def __init__(self): super().__init__()self.initUI() def initUI(self): self.creatContorls('打印控制:') self.creatResult('操作結(jié)果:') 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('預(yù)覽') numberLabel = QLabel('打印份數(shù):') pageLabel = QLabel('紙張類(lèi)型:') self.previewStatus = QCheckBox('全屏預(yù)覽') 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: '+'份數(shù):'+ 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_())
運(yùn)行該函數(shù)之后的效果如下:
示例說(shuō)明:
通過(guò)一個(gè)模擬打印的界面來(lái)詳細(xì)說(shuō)明一下關(guān)于信號(hào)的自定義,在打印的時(shí)候可以設(shè)定打印的分?jǐn)?shù),紙張類(lèi)型,觸發(fā)“打印”按鈕之后,將執(zhí)行結(jié)果顯示到右側(cè);通過(guò)全屏預(yù)覽QCheckBox來(lái)選擇是否通過(guò)全屏模式進(jìn)行預(yù)覽,將執(zhí)行結(jié)果顯示到右側(cè)。
通過(guò)點(diǎn)擊F1快捷鍵,可以顯示helpMessage信息。
代碼分析:
L12~15:
helpSignal = pyqtSignal(str)printSignal = pyqtSignal(list)#聲明一個(gè)多重載版本的信號(hào),包括了一個(gè)帶int和str類(lèi)型參數(shù)的信號(hào),以及帶str參數(shù)的信號(hào)previewSignal = pyqtSignal([int,str],[str])
通過(guò)pyqtSignal()定義了三個(gè)信號(hào),helpSignal ,printSignal ,previewSignal 。其中:
helpSignal 為str參數(shù)類(lèi)型的信號(hào); printSignal 為list參數(shù)類(lèi)型的信號(hào); previewSignal為一個(gè)多重載版本的信號(hào),包括了一個(gè)帶int和str類(lèi)型參數(shù)的信號(hào),以及str類(lèi)行的參數(shù)。L31~36:
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)
綁定信號(hào)和槽;著重說(shuō)明一下多重載版本的信號(hào)的綁定,previewSignal有兩個(gè)版本previewSignal(str),previewSignal(int,str)。由于存在兩個(gè)版本,從因此在綁定的時(shí)候需要顯式的指定信號(hào)和槽的綁定關(guān)系。
具體如下:
self.previewSignal[str].connect(self.previewPaper)
self.previewSignal[int,str].connect(self.previewPaperWithArgs)
其中[str]參數(shù)的previewSignal信號(hào)綁定previewPaper();[int,str]的previewSignal信號(hào)綁定previewPaperWithArgs()
L72~76:
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')
多重載版本的信號(hào)的發(fā)射也需要制定對(duì)應(yīng)發(fā)射的版本,類(lèi)似同信號(hào)的版定。
L78~82:
def emitPrintSignal(self): pList = [] pList.append(self.numberSpinBox.value ()) pList.append(self.styleCombo.currentText()) self.printSignal.emit(pList)
如代碼中所示,在信號(hào)發(fā)射的時(shí)候可以傳遞python數(shù)據(jù)類(lèi)型的參數(shù),在本例中傳遞list類(lèi)型的參數(shù)pList.
L93~96:
def keyPressEvent(self, event): if event.key() == Qt.Key_F1: self.helpSignal.emit('help message')
通過(guò)復(fù)寫(xiě)keyPressEvent()方法,將F1快捷鍵進(jìn)行功能的拓展。在windows的大部分應(yīng)用,我們都會(huì)使用一些快捷鍵來(lái)快速的完成某些特定的功能。比如F1鍵,會(huì)快速調(diào)出幫助界面。那我們就可以復(fù)寫(xiě)keyPressEvent()方法來(lái)模擬發(fā)送所需的信號(hào),來(lái)完成我們的對(duì)應(yīng)任務(wù).
注意事項(xiàng):
自定義的信號(hào)在init()函數(shù)之前定義; 自定義型號(hào)可以傳遞,str、int、list、object、float、tuple、dict等很多類(lèi)型的參數(shù); 注意signal和slot的調(diào)用邏輯,避免signal和slot之間出現(xiàn)死循環(huán)。如在slot方法中繼續(xù)發(fā)射該信號(hào);更多關(guān)于python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5文章請(qǐng)查看下面的相關(guān)鏈接
相關(guān)文章:
1. idea2020.1最新版永久破解/pycharm也可用(步驟詳解)2. spring boot動(dòng)態(tài)切換數(shù)據(jù)源的實(shí)現(xiàn)3. python 繪制斜率圖進(jìn)行對(duì)比分析4. Android實(shí)現(xiàn)儀表盤(pán)控件開(kāi)發(fā)5. python GUI模擬實(shí)現(xiàn)計(jì)算器6. 利用python+ffmpeg合并B站視頻及格式轉(zhuǎn)換的實(shí)例代碼7. Android自定義短信倒計(jì)時(shí)view流程分析8. IDEA下lombok安裝及找不到get,set的問(wèn)題的解決方法9. IDEA中解決 git pull 沖突的方法10. 解決django 多個(gè)APP時(shí) static文件的問(wèn)題
