1 什么时候用信号与槽
Qt建议: 只在主线程中操作界面 。
在另外一个线程直接操作界面,可能会导致意想不到的问题,比如:输出显示不全,甚至程序崩溃。
但是,我们确实经常需要在子线程中 更新界面。比如子线程是个爬虫,爬取到数据显示在界面上。
怎么办呢?
这时,推荐的方法是使用信号。
前面我们曾经看到过 各种 Qt 控件可以发出信号,比如 被点击、被输入等。
我们也可以自定义类,只要这个类继承QObject类,就能发出自己定义的各种Qt信号
2 内置信号连接自定义槽
from PySide2.QtWidgets import *import sysapp = 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:自定义信号源对象类型,一定要继承自 QObjectclass 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, Signalclass 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) -> Nonerow = self.rowgv.sig.tbe_item_set_text[int, int, str].emit(row, gv.COL_LOG, info)
4 装饰器信号与槽
import sysfrom PySide2.QtCore import *from PySide2.QtWidgets import QApplication, QWidget, QPushButtonclass 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 sysfrom PySide2.QtCore import Signalfrom PySide2.QtWidgets import QApplication, QDialog, QPushButtonclass 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)
