使用pyqt画界面,当一个点击事件过于复杂,或者出现阻塞时,这个时候往往就会导致界面卡死,而我们只是单纯的起一个线程,并不能解决问题,反而直接使整个程序崩掉,而这个时候,我们想要解决这个问题,只有使用pyqt自带的线程库QThread
网上有很多例子,大多是创建一个类,继承QThread类,然后引入一个槽函数,然后改写run方法,将会发生阻塞的代码放在run函数里面,然后通过激活槽函数,传递一个参数,从而实现异步功能
class MyThread(QThread):
countChanged = pyqtSignal(int)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
self.count = 0
def resetCount(self):
self.count = 0
def run(self):
while True:
self.msleep(100)
self.count += 1
self.countChanged.emit(self.count)
参考网址如下:
https://blog.csdn.net/seniorwizard/article/details/110824177
import time
import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread
# 装饰器,用于测量阻塞计时
def test_time(func1):
def train(self):
start_time = time.time()
res = func1(self)
end_time = time.time()
print(end_time - start_time)
# logger.info(f'the ocr parse time is {end_time-start_time} s')
return res
return train
class pictureOCR(QThread):
"""
对图片进行ocr识别,,功能服务,可单独放一个文件
"""
def __init__(self, *args, **kwargs):
super(pictureOCR, self).__init__()
@test_time
def run(self):
while True:
time.sleep(2) # 制造阻塞
print('任务执行中')
class MainWindow(QtWidgets.QMainWindow):
"""pyqt主界面"""
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# self.setupUi(self)
self.resize(500, 300)
self.p = pictureOCR()
self.pushButton = QtWidgets.QPushButton(self)
self.pushButton.setText('开始异步任务')
self.pushButton.clicked.connect(self.click_event)
def click_event(self):
self.p.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
将功能和界面分开,是不是更加清晰明了,而且界面也不会出现未响应的情况,如果你有更好的办法,欢迎一起交流
上述方法,确实能够解决异步卡顿问题,但同时引出了一个新问题,那就是在直接刷新主界面控件时,比如表格控件,并不会立即刷新,需要点击一下才可以刷新,所以还是需要在该方法中引入槽函数
改造后代码如下:
import time
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QThread
# 装饰器,用于测量阻塞计时
def test_time(func1):
def train(self):
start_time = time.time()
res = func1(self)
end_time = time.time()
print(end_time - start_time)
# logger.info(f'the ocr parse time is {end_time-start_time} s')
return res
return train
class pictureOCR(QThread):
"""
对图片进行ocr识别,,功能服务,可单独放一个文件
"""
signal = QtCore.pyqtSignal(int)
def __init__(self, *args, **kwargs):
super(pictureOCR, self).__init__()
self.main_win = kwargs.get('main_win')
self.signal.connect(self.refresh)
@test_time
def run(self):
m = 0
while True:
time.sleep(2) # 制造阻塞
m += 1
self.signal.emit(m)
print('任务执行中')
def refresh(self, m):
self.main_win.line_edit.setText(str(m))
class MainWindow(QtWidgets.QMainWindow):
"""pyqt主界面"""
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# self.setupUi(self)
self.resize(500, 300)
self.p = pictureOCR(main_win=self) # 把主函数对象传给服务,方便服务操作控件
self.pushButton = QtWidgets.QPushButton(self)
self.pushButton.setText('开始异步任务')
self.pushButton.clicked.connect(self.click_event)
self.line_edit = QtWidgets.QLineEdit(self)
self.line_edit.move(200,0)
def click_event(self):
self.p.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())