PyQt5學習筆記---信號與槽

注:信號與槽中信號和槽的關係

  1. 一個信號可以連接多個槽
  2. 一個信號可以連接另一個信號
  3. 信號參數可以是任何Python類型參數
  4. 一個槽可以監聽多個信號
  5. 信號與槽的連接方式可以是同步連接,也可以是異步連接、信號與槽的連接可能是跨線程、信號可能會斷開。

定義信號

       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()
  • 信號與槽的在細分化
  1. 內置信號與槽函數
  2. 內置信號和自定義槽函數
  3. 自定義信號和內置槽函數
  4. 自定義信號和槽函數
#自定義信號與槽
# -*- 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_())

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章