PyQt5 UI界面无响应解决方案
在GUI程序中,主线程也叫GUI线程,它是唯一被允许执行GUI相关操作的线程。对于一些耗时多的任务,如果放在主线程中,就可能会造成阻塞从而出现界面无响应的问题。先上代码:
class AppMainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(AppMainWindow, self).__init__(parent)
self.setupUi(self)
snp_path = ''
data = []
def loadSNP(self):
if self.snp_path:
self.labelFileStat.setText("Loading...")
self.labelFileStat.repaint()
self.data = file_process(self.snp_path) # 此任务耗时可达数十秒
if self.data:
self.labelFileStat.setText(str(len(self.data))+" lines of data loaded.")
else:
self.labelFileStat.setText("FAILED!!")
解决方案找到了两种:
- 使用多线程:一个线程处理应用程序用户界面的线程,另一个线程执行耗时任务()
- 调用
QApplication.processEvents()
方案1暂且按下不表,后面用到再研究,挖个坑先。
最近写的这个程序本身很简单,所以采用了方案2,在file_process()中周期性地调用QApplication.processEvents(),这个函数告诉Qt来处理任何没有被处理的事件,防止造成阻塞。Qt官方文档里也写了:
You can call this function occasionally when your program is busy doing a long operation (e.g. copying a file).
需要注意的是,processEvents()默认处理所有Qt事件,这样在耗时任务执行期间存在因用户操作而产生非预期事件的风险,例如文件处理任务执行过程中用户点击关闭窗口。QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)可以避免这种情况发生。
此外,processEvents()还支持传入maxtime参数,用于指定处理事件的最大时间,单位ms,Qt文档原话:
Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter.