一、信號和槽的創建
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_())
- 運行結果
右鍵點擊按鈕,輸出