一文詳解PyQt5中信號(hào)(Signal)與槽(Slot)
信號(hào)與槽介紹
信號(hào)(Signal)與槽(Slot)是Qt中的核心機(jī)制,也是在PyQt編程中對(duì)象之間進(jìn)行通信的機(jī)制。PyQt的窗口控件類(lèi)有很多內(nèi)置信號(hào),開(kāi)發(fā)者也可以添加自定義信號(hào)。信號(hào)與槽有如下特點(diǎn):
- 一個(gè)信號(hào)可以連接多個(gè)槽。
- 一個(gè)信號(hào)可以連接另一個(gè)信號(hào)。
- 信號(hào)參數(shù)可以使任何Python類(lèi)型。
- 一個(gè)槽可以連接到多個(gè)信號(hào)。
- 信號(hào)與槽的連接方式可以是同步連接,也可以是異步連接。
- 信號(hào)與槽的連接可能會(huì)跨線程。
- 信號(hào)可以斷開(kāi)連接。
內(nèi)置信號(hào)與槽的使用
這里演示了內(nèi)置clicked信號(hào)連接槽函數(shù)的使用
import sys from PyQt5.QtWidgets import QPushButton, QApplication, QWidget, QMessageBox app = QApplication(sys.argv) widget = QWidget() def showMsg(): QMessageBox.information(widget, "信息提示框", "Ok,彈出測(cè)試信息") btn = QPushButton("測(cè)試點(diǎn)擊按鈕", widget) btn.clicked.connect(showMsg) widget.show() sys.exit(app.exec_())
自定義信號(hào)與槽的使用
import sys from PyQt5.QtCore import QObject, pyqtSignal # 信號(hào)對(duì)象 class QTypeSignal(QObject): # 定義一個(gè)信號(hào) sendmsg = pyqtSignal(object) def __init__(self): super(QTypeSignal, self).__init__() def run(self): # 發(fā)射信號(hào) self.sendmsg.emit('Hello PyQt5') # 槽對(duì)象 class QTypeSlot(QObject): def __init__(self): super(QTypeSlot, self).__init__() # 槽對(duì)象中的槽函數(shù) def get(self, msg): print("QSlot get msg => " + msg) if __name__ == "__main__": send = QTypeSignal() slot = QTypeSlot() # 1 print("---把信號(hào)綁定到槽函數(shù)上---") send.sendmsg.connect(slot.get) send.run() # 2 print('---把信號(hào)與槽函數(shù)斷開(kāi)---') send.sendmsg.disconnect(slot.get) send.run()
自定義信號(hào)和內(nèi)置槽函數(shù)
import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtCore import Qt class WinForm (QWidget): # 自定義信號(hào),不帶參數(shù) button_clicked_signal = pyqtSignal() def __init__(self, parent=None): super(WinForm, self).__init__(parent) self.setWindowTitle("自定義信號(hào)和內(nèi)置槽函數(shù)示例") self.resize(330, 50) btn = QPushButton("關(guān)閉", self) # 連接信號(hào)與槽函數(shù) btn.clicked.connect(self.btn_clicked) # 接收信號(hào),連接到槽函數(shù) self.button_clicked_signal.connect(self.close) def btn_clicked(self): # 發(fā)送自定義信號(hào),無(wú)參數(shù) self.button_clicked_signal.emit() if __name__ == "__main__": app = QApplication(sys.argv) win = WinForm() win.show() sys.exit(app.exec_())
自定義信號(hào)和自定義槽函數(shù)
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * class WinForm(QWidget): # 自定義信號(hào),無(wú)參數(shù) button_clicked_signal = pyqtSignal() def __init__(self, parent= None): super(WinForm, self).__init__(parent) self.setWindowTitle("自定義信號(hào)和槽函數(shù)示例") self.resize(350, 50) btn = QPushButton("關(guān)閉", self) btn.clicked.connect(self.btn_clicked) self.button_clicked_signal.connect(self.btn_close) def btn_clicked(self): self.button_clicked_signal.emit() def btn_close(self): self.close() if __name__ == "__main__": app = QApplication(sys.argv) win = WinForm() win.show() sys.exit(app.exec_())
自定義有參信號(hào)
import sys from PyQt5.QtCore import pyqtSignal, QObject class CustSignal(QObject): # 聲明無(wú)參數(shù)的信號(hào) signal1 = pyqtSignal() # 聲明帶一個(gè)int類(lèi)型參數(shù)的信號(hào) signal2 = pyqtSignal(int) # 聲明帶一個(gè)int和一個(gè)str類(lèi)型參數(shù)的信號(hào) signal3 = pyqtSignal(int, str) # 聲明帶一個(gè)列表類(lèi)型參數(shù)的信號(hào) signal4 = pyqtSignal(list) # 聲明帶一個(gè)字典類(lèi)型參數(shù)的信號(hào) signal5 = pyqtSignal(dict) # 聲明一個(gè)多重載版本的信號(hào),包括帶int和str類(lèi)型參數(shù)的信號(hào)和帶str類(lèi)型參數(shù)的信號(hào) signal6 = pyqtSignal([int,str], [str]) def __init__(self, parent=None): super(CustSignal, self).__init__(parent) # 將信號(hào)連接到指定的槽函數(shù) self.signal1.connect(self.signalCall1) self.signal2.connect(self.signalCall2) self.signal3.connect(self.signalCall4) self.signal4.connect(self.signalCall4) self.signal5.connect(self.signalCall5) self.signal6[int, str].connect(self.signalCall6) self.signal6[str].connect(self.signalCall6OverLoad) # 發(fā)射信號(hào) self.signal1.emit() self.signal2.emit(100) self.signal3.emit(200, 'hello') self.signal4.emit([1,2,3,4,5,6]) self.signal5.emit({"name":"xiaowang", "age":"25"}) self.signal6[int, str].emit(300, 'hello world') self.signal6[str].emit('hello pyqt') def signalCall1(self): print('signal1 emit') def signalCall2(self, val): print('signal3 emit, value:', val) def signalCall3(self, val, text): print('signal3 emit, value:', val, text) def signalCall4(self, val): print('signal4 emit, value:', val) def signalCall5(self, val): print('signal5 emit, value:', val) def signalCall6(self, val, text): print('signal6 emit, value:', val, text) def signalCall6OverLoad(self, val): print('signal6 overload emit, value:', val) if __name__ == "__main__": custSignal = CustSignal()
使用自定義信號(hào)參數(shù)
對(duì)于clicked信號(hào)來(lái)說(shuō)他是沒(méi)有參數(shù)的,如果連接的槽函數(shù)希望可以接收參數(shù),如果直接連接有參數(shù)的槽函數(shù)會(huì)出錯(cuò),因?yàn)樾盘?hào)發(fā)出的參數(shù)個(gè)數(shù)一定要大于槽函數(shù)接收的參數(shù)個(gè)數(shù)。這里有兩種解決方法:
1.使用lambda
2.使用functools模塊中的partial函數(shù)
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from functools import partial, partialmethod class WinForm(QMainWindow): def __init__(self, parent=None): super(WinForm, self).__init__(parent) self.setWindowTitle("有參槽函數(shù)接收無(wú)參信號(hào)的解決方法") button1 = QPushButton("Button 1") button2 = QPushButton("Button 2") # 對(duì)于clicked信號(hào)來(lái)說(shuō)他是沒(méi)有參數(shù)的,如果連接的槽函數(shù)希望可以接收參數(shù),如果直接連接有參數(shù) # 的槽函數(shù)會(huì)出錯(cuò),因?yàn)樾盘?hào)發(fā)出的參數(shù)個(gè)數(shù)一定要大于槽函數(shù)接收的參數(shù)個(gè)數(shù)。這里有兩種解決方法: # 1.使用lambda # 2.使用functools模塊中的partial函數(shù) # 使用lambda button1.clicked.connect(lambda: self.onButtonClick(1)) # 使用functools模塊中的partial函數(shù) button2.clicked.connect(partial(self.onButtonClick, 2)) layout = QHBoxLayout() layout.addWidget(button1) layout.addWidget(button2) mainwidget = QWidget() mainwidget.setLayout(layout) self.setCentralWidget(mainwidget) def onButtonClick(self, n): print("Button {0} 被按下了".format(n)) QMessageBox.information(self, "信息提示框", 'Button {0} clicked'.format(n)) if __name__ == "__main__": app = QApplication(sys.argv) win = WinForm() win.show() sys.exit(app.exec_())
裝飾器信號(hào)與槽
@PyQt5.QtCore.pyqtSlot(參數(shù))
def on_發(fā)送者對(duì)象名稱(chēng)_發(fā)射信號(hào)名稱(chēng)(self, 參數(shù)):
pass
必須先執(zhí)行了這行代碼:QtCore.QMetaObject.connectSlotsByName(self)
from PyQt5 import QtCore from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QMessageBox import sys # 裝飾器信號(hào)與槽 # @PyQt5.QtCore.pyqtSlot(參數(shù)) # def on_發(fā)送者對(duì)象名稱(chēng)_發(fā)射信號(hào)名稱(chēng)(self, 參數(shù)): # pass # # 必須要先執(zhí)行這行代碼:QtCore.QMetaObject.connectSlotsByName(self) class CustWidget(QWidget): def __init__(self, parent=None): super(CustWidget, self).__init__(parent) self.setWindowTitle("裝飾器信號(hào)與槽Demo") self.resize(350, 50) self.okButton = QPushButton("OK", self) # 使用setObjectName設(shè)置對(duì)象名稱(chēng) self.okButton.setObjectName("okButton") layout = QHBoxLayout() layout.addWidget(self.okButton) self.setLayout(layout) QtCore.QMetaObject.connectSlotsByName(self) @QtCore.pyqtSlot() def on_okButton_clicked(self): print("單擊了OK按鈕") QMessageBox.information(self, "信息提示框", "單擊了OK按鈕") if __name__ == "__main__": app = QApplication(sys.argv) win = CustWidget() win.show() sys.exit(app.exec_())
信號(hào)與槽的斷開(kāi)和連接
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * # 信號(hào)與槽斷開(kāi)連接 class SignalClass(QObject): # 聲明無(wú)參數(shù)的信號(hào) signal1 = pyqtSignal() # 聲明帶一個(gè)int類(lèi)型參數(shù)的信號(hào) signal2 = pyqtSignal(int) def __init__(self, parent=None): super(SignalClass, self).__init__(parent) # 將信號(hào)signal1連接到sig1Call和sig2Call這兩個(gè)槽函數(shù) self.signal1.connect(self.sig1Call) self.signal1.connect(self.sig2Call) # 將signal2連接到signal1 self.signal2.connect(self.signal1) # 發(fā)射信號(hào) self.signal1.emit() self.signal2.emit(1) # 斷開(kāi)signal1,signal2信號(hào)與各槽函數(shù)的連接 self.signal1.disconnect(self.sig1Call) self.signal1.disconnect(self.sig2Call) self.signal2.disconnect(self.signal1) # 將信號(hào)signal1和signal2連接到同一個(gè)槽函數(shù)sig1Call self.signal1.connect(self.sig1Call) self.signal2.connect(self.sig1Call) # 再次發(fā)射信號(hào) self.signal1.emit() self.signal2.emit(2) def sig1Call(self): print('signal-1 emit') def sig2Call(self): print('signal-2 emit') if __name__ == "__main__": signal = SignalClass()
多線程中信號(hào)與槽的使用
import sys from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtCore import QThread, pyqtSignal class Main(QWidget): def __init__(self, parent=None): super(Main, self).__init__(parent) # 創(chuàng)建一個(gè)線程實(shí)例并設(shè)置名稱(chēng),變量,信號(hào)與槽 self.thread = MyThread() self.thread.setIdentity("thread1") self.thread.sinOut.connect(self.outText) self.thread.setVal(6) def outText(self, text): print(text) class MyThread(QThread): sinOut = pyqtSignal(str) def __init__(self, parent=None): super(MyThread, self).__init__(parent) self.identity = None def setIdentity(self, text): self.identity = text def setVal(self, val): self.times = int(val) # 執(zhí)行線程run方法 self.start() def run(self): while self.times > 0 and self.identity: # 發(fā)射信號(hào) self.sinOut.emit(self.identity + "==>" + str(self.times)) self.times -= 1 if __name__ == '__main__': app = QApplication(sys.argv) main = Main() main.show() sys.exit(app.exec_())
以上就是一文詳解PyQt5中信號(hào)(Signal)與槽(Slot)的詳細(xì)內(nèi)容,更多關(guān)于PyQt5信號(hào) 槽的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pytorch中transform.Compose()用法詳解
PyTorch是一個(gè)開(kāi)源的Python機(jī)器學(xué)習(xí)庫(kù),基于Torch,用于自然語(yǔ)言處理等應(yīng)用程序,這篇文章主要介紹了pytorch中transform.Compose()用法,需要的朋友可以參考下2023-10-10python之如何將標(biāo)簽轉(zhuǎn)化為one-hot(獨(dú)熱編碼)
這篇文章主要介紹了python之如何將標(biāo)簽轉(zhuǎn)化為one-hot(獨(dú)熱編碼)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Python 輸入一個(gè)數(shù)字判斷成績(jī)分?jǐn)?shù)等級(jí)的方法
今天小編就為大家分享一篇Python 輸入一個(gè)數(shù)字判斷成績(jī)分?jǐn)?shù)等級(jí)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11python異步實(shí)現(xiàn)定時(shí)任務(wù)和周期任務(wù)的方法
今天小編就為大家分享一篇python異步實(shí)現(xiàn)定時(shí)任務(wù)和周期任務(wù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06python內(nèi)置數(shù)據(jù)類(lèi)型使用方法和繼承關(guān)系
這篇文章主要介紹了python內(nèi)置數(shù)據(jù)類(lèi)型使用方法和繼承關(guān)系,介紹內(nèi)容有python包含的內(nèi)置序列、使用內(nèi)置的數(shù)據(jù)類(lèi)型等相關(guān)資料,需要的小伙伴可以參考一下2022-03-03Pytorch自定義CNN網(wǎng)絡(luò)實(shí)現(xiàn)貓狗分類(lèi)詳解過(guò)程
PyTorch是一個(gè)開(kāi)源的Python機(jī)器學(xué)習(xí)庫(kù),基于Torch,用于自然語(yǔ)言處理等應(yīng)用程序。它不僅能夠?qū)崿F(xiàn)強(qiáng)大的GPU加速,同時(shí)還支持動(dòng)態(tài)神經(jīng)網(wǎng)絡(luò)。本文將介紹PyTorch自定義CNN網(wǎng)絡(luò)實(shí)現(xiàn)貓狗分類(lèi),感興趣的可以學(xué)習(xí)一下2022-12-12Python爬蟲(chóng)XPath解析出亂碼的問(wèn)題及解決
這篇文章主要介紹了Python爬蟲(chóng)XPath解析出亂碼的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05