1 什么时候用信号与槽
Qt建议: 只在主线程中操作界面 。
在另外一个线程直接操作界面,可能会导致意想不到的问题,比如:输出显示不全,甚至程序崩溃。
但是,我们确实经常需要在子线程中 更新界面。比如子线程是个爬虫,爬取到数据显示在界面上。
怎么办呢?
这时,推荐的方法是使用信号。
前面我们曾经看到过 各种 Qt 控件可以发出信号,比如 被点击、被输入等。
我们也可以自定义类,只要这个类继承QObject类,就能发出自己定义的各种Qt信号
2 内置信号连接自定义槽
from PySide2.QtWidgets import *
import sys
app = QApplication()
widget = QWidget()
def showMsg():
QMessageBox.information(widget, "提示", "HelloWorld")
btn = QPushButton("测试点击", widget)
btn.clicked.connect(showMsg)
widget.show()
sys.exit(app.exec_())
3 自定义信号与槽
(1) 信号给槽传递一个参数
from PySide2.QtCore import QObject, Signal
# 要点1:自定义信号源对象类型,一定要继承自 QObject
class MySignal(QObject):
# 要点2:每一种信号 都要定义为 为的静态属性
sig1 = Signal(object) # 只传一个参数, object表示可以传任意py类型
def func(msg):
print("槽函数接收到的信号为", msg)
if __name__ == "__main__":
# 要点3:必须实例化才能调用信号的connect和emit方法
my_signal = MySignal()
my_signal.sig1.connect(func)
my_signal.sig1.emit("HelloWorld")
运行结果:
槽函数接收到的信号为 HelloWorld
(2) 信号给槽传递多个指定类型的参数
from PySide2.QtCore import QObject, Signal
class MySignal(QObject):
sig1 = Signal(bool, str, list)
def func(*args):
print("槽函数接收到的信号为", args)
if __name__ == "__main__":
my_signal = MySignal()
my_signal.sig1.connect(func)
my_signal.sig1.emit(1, "123", [4,5,6])
运行结果:
槽函数接收到的信号为 (True, ‘123’, [4, 5, 6])
(3) 重载信号与槽
# 在mf.py中定义自定义信号
class MySignal(QObject):
# [row, col, hwnd] 或 [int, int, info]
tbe_item_set_text = Signal([int, int, int], [int, int, str])
# 在自定义的ui窗口类中定义此方法
def init_sig_slot(self):
gv.sig = mf.MySignal()
gv.sig.tbe_item_set_text[int, int, int].connect(
lambda row, col, hwnd: self.tbe_console.item(row, col).setText(str(hwnd))
)
gv.sig.tbe_item_set_text[int, int, str].connect(
lambda row, col, info: self.tbe_console.item(row, col).setText(info)
)
# 调用
class WndWorker():
...
def log_out(self, info):
# type: (str) -> None
row = self.row
gv.sig.tbe_item_set_text[int, int, str].emit(row, gv.COL_LOG, info)
4 装饰器信号与槽
import sys
from PySide2.QtCore import *
from PySide2.QtWidgets import QApplication, QWidget, QPushButton
class MyWidget(QWidget):
def __init__(self):
super().__init__()
# 创建对象并设置对象名
self.btn_ok = QPushButton("OK", self)
self.btn_ok.setObjectName("btn_ok")
# 通过对象名连接槽
QMetaObject.connectSlotsByName(self)
@Slot()
def on_btn_ok_clicked(self):
print("单击了ok按钮")
if __name__ == "__main__":
app = QApplication()
my_wgt = MyWidget()
my_wgt.show()
sys.exit(app.exec_())
5 常用自定义信号方式
import sys
from PySide2.QtCore import Signal
from PySide2.QtWidgets import QApplication, QDialog, QPushButton
class WndClientLogin(QDialog):
logined = Signal()
def __init__(self):
super().__init__()
self.btn = QPushButton("test", self)
self.btn.clicked.connect(
lambda : self.logined.emit()
)
self.logined.connect(self.accept)
if __name__ == '__main__':
app = QApplication()
wnd_login = WndClientLogin()
wnd_login.show()
if wnd_login.exec_() == QDialog.Accepted:
print("已接受")
sys.exit(0)