3.3 信號和槽的創建+自定義信號(pyqtSignal)的原理和方法


一、信號和槽的創建

1.信號和槽的介紹

  • 每一個QObject對象和所有繼承自QWidget的控件(這些都是 QObject 的子對象)都支持信號與槽機制。
  • 當信號發射時,連接的槽函數將會自動執行。
  • 信號與槽通過object.signal.connect()方法連接。

信號與槽具有如下特點。

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

示意圖:

API中信號與槽的更詳細解釋,可以參考官方網站:

2.定義信號

1> 為QObject對象創建信號

  • 使用pyqtSignal()函數創建一個或多個重載的未綁定的信號作為類的屬性,信號只能在QObject的子類中定義
  • 信號必須在類創建時定義,不能在類創建后作為類的屬性動態添加進來。
  • 信號可以傳遞多個參數,並指定信號傳遞參數的類型,參數類型是 標准的Python數據類型(字符串、日期、布爾類型、數字、列表、元組和字典)
    2> 為控件創建信號
  • 為自定義控件WinForm創建了一個btnClickedSignal信號。
class WinForm(QMainWindow):
btnClickedSignal=pyqtSignal()

3.操作信號

  • 使用connect()函數可以把信號綁定到槽函數上
  • 使用disconnect()函數可以解除信號與槽函數的綁定
  • 使用emit()函數可以發射信號

4.信號與槽的入門應用

1>內置信號與槽的使用

  • 是指在發射信號時,使用窗口控件的函數,而不是自定義的函數。
  • 代碼
from PyQt5.QtWidgets import QPushButton, QApplication, QWidget
from PyQt5.QtWidgets import QMessageBox
import sys

app = QApplication(sys.argv)
widget = QWidget()


def showMsg() :
    QMessageBox.information(widget, "信息提示框", "ok,彈出測試信息")


btn = QPushButton("測試點擊按鈕", widget)
btn.clicked.connect(showMsg)
widget.show()
sys.exit(app.exec_())

  • 效果

2>自定義信號與槽的使用

  • 指在發射信號時,不使用窗口控件的函數,而是使用自定義的函數(簡單地說,就是使用 pyqtSignal 類實例發射信號)
  • 代碼
"""
    【簡介】
    內置信號槽示例
"""

from PyQt5.QtCore import QObject, pyqtSignal


# 信號對象
class QTypeSignal(QObject) :
    # # 定義一個信號
    # sendmsg = pyqtSignal(object)

    #定義含有兩個參數的信號
    sendmsg = pyqtSignal(str,str)

    def __init__(self) :
        super(QTypeSignal, self).__init__()

    def run(self) :
        # 發射信號
        # # 傳遞一個參數
        # self.sendmsg.emit('Hello Pyqt5')
        # 傳遞兩個參數
        self.sendmsg.emit('第一個參數', '第二個參數')


# 槽對象
class QTypeSlot(QObject) :
    def __init__(self) :
        super(QTypeSlot, self).__init__()

    # 槽對象里的槽函數

    # def get(self, msg) :
    #     print("QSlot get msg => " + msg)

    def get(self, msg1, msg2) :
        print("QSlot get msg => " + msg1 + ' ' + msg2)


if __name__ == '__main__' :
    send = QTypeSignal()
    slot = QTypeSlot()
    # 1
    print('--- 把信號綁定到槽函數 ---')
    send.sendmsg.connect(slot.get)
    send.run()

    # 2
    print('--- 把信號斷開槽函數 ---')
    send.sendmsg.disconnect(slot.get)
    send.run()
  • 運行結果

3>裝飾器的信號與槽的使用

  • 是第一種的衍生,后面會介紹

5.自定義信號(pyqtSignal)的原理和方法

1> 基本原理

  • 自定義信號是通過pyqtSignal函數以類屬性的方式在被重寫的類內部實現的,這里的類屬性和實例屬性一定要區分清楚,不能再pyqtSignal之前加self。
  • pyqtSignal()函數也可以傳遞不同的參數。

2> 代碼

  • 思路:
    自定義按鈕類:
    1.定義好一個信號
    2.尋找這個信號所觸發的事件
    3.在事件內部調用父類功能事件+邏輯判斷->通過emit函數把定義的信號發出去
    定義窗口類:
    1.init函數
    2.func_list函數
    3.對應func函數->內部定義槽函數+利用自定義信號connect連接
點擊查看代碼
from PyQt5.Qt import *
import sys

#自定義信號
class Btn(QPushButton) :
    rightSignal = pyqtSignal()  # 先定義好一個信號,然后尋找這個信號所屬事件
    #通過事件來觸發,需要重寫事件
    def mousePressEvent(self, evt) :
        super().mousePressEvent(evt) #調用父類功能
        # print(evt.button())  # QMouseEvent
        # if evt.button() == 2:
        if evt.button() == Qt.RightButton :#左鍵是1 右鍵是2
            # print('鼠標右鍵被按下')  # 這是用來測試右鍵是否生效,不是槽函數功能
            self.rightSignal.emit()  # 通過emit函數來把之定義的信號發射出去,以實現后面與槽函數的連接
        pass


class Window(QWidget) :
    def __init__(self) :
        super().__init__()
        self.setWindowTitle("自定義信號的原理和方法")
        self.resize(600, 500)
        self.func_list()

    def func_list(self) :
        self.func()

    def func(self) :
        # btn = QPushButton(self)
        btn = Btn(self)
        btn.setText('按鈕')
        btn.move(200, 100)

        #槽函數
        def btn_press() :
            print('鼠標被按下')

        #btn.pressed.connect(btn_press)  #內置信號pressed與槽函數連接,只有左鍵按時會有反應
        btn.rightSignal.connect(btn_press) #用自定義信號連接槽函數,並把槽函數內的內容輸出


if __name__ == '__main__' :
    app = QApplication(sys.argv)
    window = Window()

    window.show()
    sys.exit(app.exec_())
  • 運行結果
    右鍵點擊按鈕,輸出


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM