即时刷新
问题简介
- 近来在项目中遇到一个问题,用PYQT5实现KNN算法的手写文字识别练习项目,在做训练集过程中,调用信号与槽,将训练执行状态在界面的QLable中显示,但是信号也发送了,槽函数也调用了,槽函数中的打印语句也执行了,就是QLable死活更改不成功,窗体的SetWindowText也可以实现。
程序假死.png
解决办法
-
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态。例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响应用户的任何操作,窗口也不会重新绘制,从而处于“无法响应”状态,这是一个非常糟糕的体验 。
在这种情况下,有一种方法是使用多线程,即在子线程中处理文件保存,主线程负责界面相关。
而如果不想使用多线程,最简单的办法就是在文件保存过程中频繁调用QApplication.processEvents()。该函数的作用是让程序处理那些还没有处理的事件,然后再把使用权返回给调用者。
先写一个简单的demo
import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.Qt import QIcon
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel
import time
class Communicate(QObject):
closeApp = pyqtSignal()
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.c = Communicate()
self.c.closeApp.connect(self.showMsg)
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Emit signal')
self.lable = QLabel("hello", self)
self.show()
def mousePressEvent(self, event):
self.c.closeApp.emit()
def showMsg(self):
print("ok")
self.lable.setText("hahah")
time.sleep(10)
self.lable.setText("wait")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
- 点击尽管可以打印出ok,但是无法将hello改为hahah,在程序假死结束之后则会直接改为wait,或者说执行过但是看不出来
执行.gif
-
将QApplication.processEvents()加入槽函数中即可解决这个问题
def showMsg(self): print("ok") self.lable.setText("hahah") QApplication.processEvents() time.sleep(10) self.lable.setText("wait")
执行2.gif