注:信號與槽中信號和槽的關係
- 一個信號可以連接多個槽
- 一個信號可以連接另一個信號
- 信號參數可以是任何Python類型參數
- 一個槽可以監聽多個信號
- 信號與槽的連接方式可以是同步連接,也可以是異步連接、信號與槽的連接可能是跨線程、信號可能會斷開。
定義信號
PyQt的內置信號是自動定義的,使用PyQt5.QtCore.pyqtSignal()可以爲QObject創建一個信號,使用pySignal()函數可以將信號定義爲類的屬性。
信號必須在類創建時定義,不能在類創建後作爲屬性動態添加進來。且必須在QObject的子類中定義。
信號可傳遞多個參數,並制定信號參數傳遞的類型,參數是標準的python類型(字符串、日期、布爾、數字、列表、元組、字典)
信號基本使用操作
使用pySignal()創建一個自定義信號,使用connect()連接信號到槽函數、使用disconnect()斷開信號和槽的連接,使用emit()發射信號
- 內置信號與槽的使用
指的是在發射信號時,使用窗口控件的函數,而非自定義函數,通過使用QObject.signal.connect將一個QObject 信號連接到另一個QObject函數
#QObject signal connect
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
app=QApplication([])
widget=QWidget()
def showMsg():
QMessageBox.information(widget,"info","ok,test msg")
btn=QPushButton("test",widget)
btn.clicked.connect(showMsg) #將按鈕的內置消息 點擊 連接到 showMsg槽函數
widget.show()
sys.exit(app.exec_())
- 自定義信號與槽的使用
指在發射信號時,不使用窗口控件函數,而使用自定義的函數(使用pyqtSignal類實例發射信號)
#自定義信號與槽
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
#信號類
class QTypeSiganl(QObject):
#優先定義帶一個參數的信號
sendMsg=pyqtSignal(object)
#定義帶兩個參數的信號
# sendMsg=pyqtSignal(param1,param)
def __init__(self):
super(QTypeSiganl, self).__init__()
def run(self):
#發射信號並帶有參數hello pyqt
self.sendMsg.emit("hello pyqt \n")
#槽函數類
class QTypeSlot(QObject):
def __init__(self):
super(QTypeSlot, self).__init__()
def get(self,msg):
print("QSlot get msg " + msg +"\n")
if __name__ == "__main__":
send=QTypeSiganl()
slot=QTypeSlot()
#連接信號(sendMsg)與槽函數(slot.get)
send.sendMsg.connect(slot.get)
send.run()
#斷開連接信號(sendMsg)與槽函數(slot.get)
send.sendMsg.disconnect(slot.get)
#再次發送是不會觸發槽函數
send.run()
- 信號與槽的在細分化
- 內置信號與槽函數
- 內置信號和自定義槽函數
- 自定義信號和內置槽函數
- 自定義信號和槽函數
#自定義信號與槽
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WinForm(QWidget):
#自動定義信號不帶參數
btn_clicked_signal=pyqtSignal()
def __init__(self):
super(WinForm, self).__init__()
self.resize(300,100)
btn=QPushButton("CLOSE",self)
# #使用空間內置信號和內置槽函數
# btn.clicked.connect(self.close)
# #使用空間內置信號和自定義槽函數
# btn.clicked.connect(self.btn_close)
# #使用內置信號clicked連接到自定義槽函數,發射自定義信號
# btn.clicked.connect(self.btn_clicked)
# #將自定義信號連接到內置槽函數
# self.btn_clicked_signal.connect(self.close)
#使用內置信號clicked連接到自定義槽函數,發射自定義信號
btn.clicked.connect(self.btn_clicked)
# 將自定義信號連接到自定義槽函數
self.btn_clicked_signal.connect(self.btn_close)
#自定義槽函數,槽函數就是一個正常的類的成員函數
def btn_clicked(self):
#發送自定義信號
self.btn_clicked_signal.emit()
def btn_close(self):
self.close()
if __name__=="__main__":
app=QApplication(sys.argv)
demo=WinForm()
demo.show()
sys.exit(app.exec_())
- 信號與槽的高級方式
即自定義信號與槽和自定義傳遞參數(數據類型爲python基本類型)
#自定義信號與槽 高級玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
# #通過類成員變量定義帶參數信號
class Siganl(QWidget):
#無參數信號
signal_no_param=pyqtSignal()
#帶一個參數(整數)的信號
signal_One_param=pyqtSignal(int)
#帶一個參數(整數或字符串)的重載信號
signal_One_param_overload=pyqtSignal([int],[str])
#帶兩個參數(整數和字符串)的信號
signal_two_param=pyqtSignal(int,str)
# 帶兩個參數([整數和整數]、[整數和字符串])的重載信號
signal_two_param_overload=pyqtSignal([int,int],[int,str])
#聲明一個帶列表參數的信號
signal_list_param=pyqtSignal(list)
# 聲明一個帶字典參數的信號
signal_dict_param=pyqtSignal(dict)
def __init__(self):
super(Siganl, self).__init__()
self.connectSignalSlot()
#定義槽函數
#無參數槽函數
def setValue_NoParam(self):
print("No Param")
#帶一個參數(整數)的槽函數
def setValue_One_Param(self,nIndex):
print("setValue One Param %d" % nIndex)
#帶一個參數(字符串)的槽函數
def setValue_One_Param_Str(self,szIndex):
print("One Param str %s " % szIndex)
#帶兩個參數(整數,整數)的槽函數
def setValue_Two_Param(self,x,y):
print("two Param IntInt %d %s" % (x,y))
#帶兩個參數(整數,字符串)的槽函數
def setValue_Two_Param_Str(self,x,szy):
print("two Param IntStr %d %s" % (x, szy))
def setValue_list_Param(self,listVal):
print("list value ",listVal)
def setValue_dict_Param(self,dictVal):
print("dict value ", dictVal)
#連接信號槽
def connectSignalSlot(self):
#連接無參數
self.signal_no_param.connect(self.setValue_NoParam)
#連接帶一個參數的
self.signal_One_param.connect(self.setValue_One_Param)
# 連接帶一個參數(整數或字符串)的重載信號
self.signal_One_param_overload[int].connect(self.setValue_One_Param)
# 連接帶一個參數(整數或字符串)的重載信號
self.signal_One_param_overload[str].connect(self.setValue_One_Param_Str)
# 連接帶兩個參數的信號
self.signal_two_param.connect(self.setValue_Two_Param)
# 連接帶兩個參數(整數和字符串)的信號
self.signal_two_param_overload[int,int].connect(self.setValue_Two_Param)
# 連接帶兩個參數([整數和字符串])的重載信號
self.signal_two_param_overload[int,str].connect(self.setValue_Two_Param_Str)
self.signal_list_param.connect(self.setValue_list_Param)
self.signal_dict_param.connect(self.setValue_dict_Param)
#發射信號
def mousePressEvent(self, event):
#發射無參信號
self.signal_no_param.emit()
#發射連接帶一個參數的信號
self.signal_One_param.emit(1)
# 發射連接帶一個參數(整數或字符串)的重載信號
self.signal_One_param_overload[int].emit(2)
# 發射連接帶一個參數(整數或字符串)的重載信號
self.signal_One_param_overload[str].emit("ryt")
# 發射連接帶兩個參數的信號
self.signal_two_param.emit(3,"213123")
# 發射連接帶兩個參數(整數和字符串)的信號
self.signal_two_param_overload[int,int].emit(1,2)
# 發射連接帶兩個參數([整數和整數]、[整數和字符串])的重載信號
self.signal_two_param_overload[int,str].emit(4,"qwe")
#發射列表數據信號
litVal=[1,2,3,4]
self.signal_list_param.emit(litVal)
# 發射字典數據信號
dictVal={"N":1,"M":2,"I":3,"J":4}
self.signal_dict_param.emit(dictVal)
if __name__=="__main__":
app=QApplication(sys.argv)
demp=Siganl()
demp.show()
sys.exit(app.exec_())
- 裝飾器信號與槽 採用裝飾器的方式來定義信號和槽函數。
使用方法
@PyQt5.QtCore.pyqtSlot(參數)
def on_發送者對象名稱_發射信號名稱(self,參數)
pass
Tips:
發送者對象名稱:即用setObjectName函數設置的名稱
發射信號名稱 :內置信號或者自定義信號的名稱
使用上述方法前提是必須先執行下面這句
QMetaObject.connectSlotByName(QObject)
#自定義裝飾器信號與槽 高級玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
import sys
class CustWidget(QWidget):
def __init__(self):
super(CustWidget, self).__init__()
self.onBtn=QPushButton("OK",self)
#使用setObjectName設置按鈕控件名稱
self.onBtn.setObjectName("okButton")
layout=QHBoxLayout(self)
layout.addWidget(self.onBtn)
self.setLayout(layout)
#不能缺少且必須先運行
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_okButton_clicked(self):
print("clicked button")
#帶參數槽函數
# @QtCore.pyqtSlot(int)
# def on_inputSpinBox1_valueChanged(self, value):
# self.outputWidget.setText(str(value + self.inputSpinBox2.value()))
if __name__=="__main__":
app=QApplication(sys.argv)
demo=CustWidget()
demo.show()
sys.exit(app.exec_())
- 多線程中信號與槽使用
#自定義信號與槽 高級玩法
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MyWidgt(QWidget):
def __init__(self):
super(MyWidgt, self).__init__()
#創建一個信號,並設置名稱、變量、信號與槽
self.thread=MyThread()
self.thread.setIdentify("th1")
#線程中的信號綁定當前類槽函數
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):
super(MyThread, self).__init__()
self.identify=None
def setIdentify(self,text):
self.identify=text
def setVal(self,val):
self.times=int(val)
#運行線程執行run
self.start()
def run(self):
while self.times>0 and self.identify:
self.sinout.emit(self.identify +"===>"+str(self.times))
self.times-=1
if __name__=="__main__":
app=QApplication(sys.argv)
demo=MyWidgt()
demo.show()
sys.exit(app.exec_())