目录
方法一:
有一个应用场景,pyqt5执行过程中,启动一个QThread执行耗时操作,QThread执行过程中,会生成数据,生成的数据需要实时展示,这时候主程序在收到数据后,会调用QDialog实时展示,需要将数据由QThread传递到QDialog中,QDialog是一个单独的模块供主程序调用,在调用时,需要先启动QDialog,然后再调用QThread,下面是一个示例:
思路:
1. QThread中定义一个信号,QThread调用逻辑函数时,将自己定义的信号传递进去,由逻辑函数使用该信号发送产生的数据;
2. 主程序实例化QThread,并将QThread的信号与槽函数绑定;
3. 主程序定义一个跟QThread信号相同的信号,启动QDialog,并与QDialog中的函数中的槽函数进行绑定,这样主程序发送的信号就会由QDialog中的函数处理;
4. 在步骤2中QThread绑定的槽函数主要是接收QThread信号产生的数据,并由主函数创建的相同类型的信号发送出去,再有QDialog对象中的函数处理。
import sys
import time
from PyQt5.QtCore import pyqtSignal, QThread, Qt
from PyQt5.QtWidgets import QDialog, QPushButton, QHBoxLayout, QApplication, QVBoxLayout, QMainWindow, QWidget
# 实际执行的逻辑程序,被thread程序调用
class AA():
# test_signal = pyqtSignal(str, list)
def __init__(self, signal_trig):
self.test_signal = signal_trig # 接收Thread传递进来的信号
self.hello()
# 写逻辑函数
def hello(self):
for x in range(20):
self.test_signal.emit(f'我是AA类{x}', list(range(10))) # 使用Thread信号发送生成的数据
time.sleep(2)
# 多线程函数--->被主程序调用
class My_thread(QThread):
thread_trig = pyqtSignal(str, list)
def __init__(self):
super(My_thread, self).__init__()
def run(self):
a = AA(self.thread_trig) # 将接收的信号传给调用的程序
# 主程序调用QDialog弹窗,Dialog弹窗会实时处理数据
class My_Dialog_test_signal(QDialog):
# dialog_trig = pyqtSignal(str, list)
def __init__(self, parent=None):
super(My_Dialog_test_signal, self).__init__(parent)
self.initUi()
# self.dialog_trig.connect(self.trig_func)
def initUi(self):
vLayout = QVBoxLayout()
btn = QPushButton('QDialog测试按钮')
vLayout.addWidget(btn)
self.setLayout(vLayout)
self.resize(200, 200)
self.show()
def trig_func(self, ss, lst):
print(ss, lst)
# 主界面程序
class CC(QWidget):
trig = pyqtSignal(str, list)
def __init__(self):
super(CC, self).__init__()
self.initUi()
def initUi(self):
btn = QPushButton('单击接收信号')
self.resize(300, 300)
hLayout = QHBoxLayout()
hLayout.addWidget(btn)
self.setLayout(hLayout)
btn2 = QPushButton('测试弹窗信号')
hLayout.addWidget(btn2)
btn.clicked.connect(self.btn_click)
btn2.clicked.connect(self.test_threadSignal)
# 点击按钮调用Thread
def btn_click(self):
# self.t = My_thread(self.trig)
self.t = My_thread() # 传给My_thread
self.t.thread_trig.connect(self.cc_print) # 将Thread中的信号绑定槽函数
self.t.start()
def test_threadSignal(self):
tmp = My_Dialog_test_signal(self)
self.trig.connect(tmp.trig_func) # 将主程序的信号绑定弹窗QDialog中的函数
# 接收Thread信号发出来的值,并由主程序中的信号再次发送出去,由Dialog中的程序处理
def cc_print(self, ss, lst):
self.trig.emit(ss, lst)
if __name__ == '__main__':
# PyQt5高清屏幕自适应设置,以及让添加的高清图标显示清晰,不然designer导入的图标在程序加载时会特别模糊
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
main_win = CC()
main_win.show()
sys.exit(app.exec_())
方法二:
1. 在QDialog中定义一个信号,并在其内部绑定槽函数;
2. 主程序调用QDialog窗口,并获取其信号;
3. 主程序调用QThread,并将步骤二中获取的信号,传给QThread;
4. thread调用实际的逻辑处理函数,并将主程序传递进来的信号,传递给逻辑函数;
5. 逻辑函数使用该信号发送数据;
import sys
import time
from PyQt5.QtCore import pyqtSignal, QThread, Qt
from PyQt5.QtWidgets import QDialog, QPushButton, QHBoxLayout, QApplication, QVBoxLayout, QMainWindow, QWidget
# 实际执行的逻辑程序,被thread程序调用
class AA():
# test_signal = pyqtSignal(str, list)
def __init__(self, signal_trig):
self.test_signal = signal_trig # 接收Thread传递进来的信号,实际为QDialog中定义的信号
self.hello()
# 写逻辑函数
def hello(self):
for x in range(20):
self.test_signal.emit(f'我是AA类{x}', list(range(10))) # 使用QDialog信号发送数据,会直接被dialog自己的程序处理
time.sleep(2)
# 多线程函数--->被主程序调用
class My_thread(QThread):
def __init__(self, trig):
super(My_thread, self).__init__()
self.trig = trig # 获取主程序传递进来的dialog中的信号
def run(self):
a = AA(self.trig) # 将dialog信号传递给实际执行的逻辑函数
# 主程序调用QDialog弹窗,Dialog弹窗会实时处理数据
class My_Dialog_test_signal(QDialog):
dialog_trig = pyqtSignal(str, list) # 只在dialog中定义信号
def __init__(self, parent=None):
super(My_Dialog_test_signal, self).__init__(parent)
self.initUi()
self.dialog_trig.connect(self.trig_func) # dialog内部处理自己信号发出的值
def initUi(self):
vLayout = QVBoxLayout()
btn = QPushButton('QDialog测试按钮')
vLayout.addWidget(btn)
self.setLayout(vLayout)
self.resize(200, 200)
self.show()
# dialog_trig发出的信号处理函数
def trig_func(self, ss, lst):
print(ss, lst)
# 主界面程序
class CC(QWidget):
def __init__(self):
super(CC, self).__init__()
self.initUi()
def initUi(self):
btn = QPushButton('单击接收信号')
self.resize(300, 300)
hLayout = QHBoxLayout()
hLayout.addWidget(btn)
self.setLayout(hLayout)
btn2 = QPushButton('测试弹窗信号')
hLayout.addWidget(btn2)
btn.clicked.connect(self.btn_click)
btn2.clicked.connect(self.test_threadSignal)
# 点击按钮调用Thread
def btn_click(self):
self.t = My_thread(self.mgs_trig) # 将dialog中的信号传递给QThread
self.t.start()
# 点击按钮,调用Dialog窗口
def test_threadSignal(self):
tmp = My_Dialog_test_signal(self)
self.mgs_trig = tmp.dialog_trig # 获取dialog对象中的信号
# 接收Thread信号发出来的值,并由主程序中的信号再次发送出去,由Dialog中的程序处理
def cc_print(self, ss, lst):
self.trig.emit(ss, lst)
if __name__ == '__main__':
# PyQt5高清屏幕自适应设置,以及让添加的高清图标显示清晰,不然designer导入的图标在程序加载时会特别模糊
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
main_win = CC()
main_win.show()
sys.exit(app.exec_())