先贴主函数入口文件代码:
代码思路点击pushbutton1、2、3则其绑定的回调函数pushbutton1、2、3 callback分别执行。
结论:由于pushbutton1每次回调都创建MyQthread实例,会卡UI,并且都会调用析构函数在终端输出“析构Mythread 实例”,有一点不解的终端竟然先出析构信息,后执行子线程(输出10987654321),求高手解答
pushbutton2、3(它俩一样的)都不会卡UI,并且每次点击按钮终端不会输出“析构Mythread 实例”
在线程MyQthread创建的时候加了参数main_ui用于传入主UI(可能不规范,可能会导致安全性不行),用来在线程执行中读取界面参数,至于能否直接修改界面显示元件内容还没实验,参考了许多博客都没有提及也没有提及如何在子线程内读取UI界面参数的博客,本文系原创,测试ok。关于Qthread::wait()可以参看https://bbs.csdn.net/topics/394475904
import sys,time
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QThread,pyqtSignal
from ui_find_usdt import Ui_UI_Usdt #导入PyQt5 UI界面自动生成的class
def get_exchange_usdt_addr(filename):
print(filename)
return {"filename":filename}
def handle_usdt(main_ui):
try:
data_path = main_ui.lineEdit.text()
time0 = main_ui.dateTimeEdit.text()
time1 = main_ui.dateTimeEdit_2.text()
filename = main_ui.lineEdit_3.text()
usdt_dic = get_exchange_usdt_addr(filename)#
#故意设置的时延,用来检验UI界面是否会出现未响应
sleeptime = 10
while(sleeptime>0):
print(sleeptime)
sleeptime = sleeptime-1
time.sleep(1)
return "{}\r\n{}\r\n{}\r\n{}\r\n{}".format(data_path,filename,time0,time1,str(usdt_dic))
except Exception as err:
print(err)
class MyQthread(QThread):
signal = pyqtSignal(str) # 括号里填写信号传递的参数
def __init__(self,main_ui):#run函数内访问UI读取参数,创建实例的时候记得传入UI实例
super().__init__()
self.main_ui=main_ui
def __del__(self):
print("析构Mythread 实例")
self.wait()#不懂参看https://bbs.csdn.net/topics/394475904
def run(self):
msg = handle_usdt(self.main_ui)
self.signal.emit(msg) # 发射信号
class fun_main(Ui_UI_Usdt):
def __init__(self,window_obj):
Ui_UI_Usdt.__init__(self)
Ui_UI_Usdt.setupUi(self,window_obj)
self.mythread3 = MyQthread(self)#在UI对象创建时添加MyQthread实例
self.mythread3.signal.connect(self.pushButton_3_callafter)
#self.mythread3运行结束发送的信号绑定到UI对象内的函数上用于更新显示
self.mythread2 = MyQthread(self)
self.mythread2.signal.connect(self.pushButton_2_callafter)
self.pushButton.clicked.connect(self.pushButton_callback)#UI按钮绑定回调函数
self.pushButton_2.clicked.connect(self.pushButton_2_callback)
self.pushButton_3.clicked.connect(self.pushButton_3_callback)
def pushButton_callback(self):#按钮1的回调函数与2、3不同,每次回调都创建MyQthread,会卡UI
print(self.pushButton.text())
self.textBrowser.setText("")
thread_callback = MyQthread(self)
thread_callback.signal.connect(self.pushButton_callafter)
thread_callback.start()
def pushButton_callafter(self,msg):
self.textBrowser.setText(msg)
def pushButton_2_callback(self):
print(self.pushButton_2.text())
self.textBrowser.setText("")
self.mythread2.start()
def pushButton_2_callafter(self,msg):
self.textBrowser.setText(msg)
def pushButton_3_callback(self):
print(self.pushButton_3.text())
self.textBrowser.setText("")
self.mythread3.start()
def pushButton_3_callafter(self,msg):
print(msg)
self.textBrowser.setText("123")
if __name__=='__main__':
app = QApplication(sys.argv)
Mwindow = QMainWindow()
ui = fun_main(Mwindow)
Mwindow.show()
sys.exit(app.exec())
二、关于自己新建的线程类里面可以不写自定义信号而使用标准信号,线程可以多信号,参考https://blog.csdn.net/weixin_41622043/article/details/87880106比如在UI类内部设定收到这些信号,未测试
#相应的mythread类内要发送该信号则可以这样写:
class mythread(QThread):
'''线程类'''
def __init__(self,main_ui):
QThread.__init__(self)
def __del__(self):
self.wait()
def myfunc(self, main_ui):
return main_ui.pushButton.text()
def run(self):
msg = myfunc(self, main_ui)
self.emit(SIGNAL("自定义字符串"), msg)
class ThreadingTutorial(QtGui.QMainWindow, design.Ui_MainWindow):
"""主逻辑类,需要继承UI类"""
def __init__(self):
super().__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.test)
self.mythread = mythread(self)
self.mythread.connect(SIGNAL("finished()"), self.done)#绑定结束信号,不传参数
self.mythread.connect(SIGNAL("自定义字符串"), self.display)#绑定自定义信号,有参msg
def test(self):
self.mythread.start()
def done(self):#接收结束信号,不传参数
print("thread finished")
def display(self,msg): #接收结束信号,传参msg
print(msg)
以上理解可能出错的是
self.emit(SIGNAL("自定义字符串"), msg)
self.mythread.connect(SIGNAL("自定义字符串"), self.display)#绑定自定义信号,有参msg
可以参考https://nikolak.com/pyqt-threading-tutorial/,应该需要填写函数和函数接收参数类型的样子
关于信号可以参考https://www.riverbankcomputing.com/static/Docs/PyQt5/#