在 PyQt 4 应用程序中,如果在事件循环中执行长耗时操作,则可能会导致 GUI 界面冻结。这通常是由于应用程序对事件的响应速度不够快,导致排队的事件无法得到及时的处理。
在下面的代码示例中,我们就遇到这样的问题。这个程序用于演示一个简单的计数器,每隔一段时间增加计数器的值并更新一个标签控件的值。但是,当程序运行一段时间后,GUI 界面就会冻结,而计数器仍在继续运行。
from PyQt4 import QtGui, QtCore
import sys
class main_window(QtGui.QWidget):
def __init__(self, parent=None):
# Layout
QtGui.QWidget.__init__(self, parent)
self.bt = QtGui.QPushButton('crash')
self.lbl = QtGui.QLabel('count')
ver = QtGui.QHBoxLayout(self)
ver.addWidget(self.bt)
ver.addWidget(self.lbl)
self.cnt = 0
self.running = False
self.connect(self.bt, QtCore.SIGNAL("clicked()"), self.count)
def count(self):
self.running = True
while self.running:
self.cnt += 1
print(self.cnt)
self.lbl.setText(str(self.cnt))
self.repaint()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mw = main_window()
mw.show()
sys.exit(app.exec_())
2、解决方案
为了解决这个冻结问题,我们可以通过以下两种方式实现:
解决方案 1:使用 QtGui.QApplication.processEvents()
方法
在长耗时操作中,我们需要调用 QtGui.QApplication.processEvents()
方法,让应用程序有机会处理排队的事件。这将使 GUI 界面保持响应,并防止它冻结。
def count(self):
self.running = True
while self.running:
self.cnt += 1
print(self.cnt)
self.lbl.setText(str(self.cnt))
QtGui.QApplication.processEvents()
解决方案 2:使用 QTimer
类
我们可以使用 QTimer
类来实现一个定时器,每隔一段时间触发一个信号,从而执行计数器操作。这将使程序以非阻塞的方式执行计数器操作,而不会阻塞 GUI 界面。
class main_window(QtGui.QWidget):
def __init__(self, parent=None):
# Layout
QtGui.QWidget.__init__(self, parent)
self.bt = QtGui.QPushButton('crash')
self.lbl = QtGui.QLabel('count')
ver = QtGui.QHBoxLayout(self)
ver.addWidget(self.bt)
ver.addWidget(self.lbl)
self.cnt = 0
self.running = False
self.timer = QtCore.QTimer(self)
self.timer.setInterval(100) # Set the timer interval in milliseconds
self.timer.timeout.connect(self.count)
self.connect(self.bt, QtCore.SIGNAL("clicked()"), self.start_counting)
def start_counting(self):
self.running = True
self.timer.start()
def stop_counting(self):
self.running = False
self.timer.stop()
def count(self):
self.cnt += 1
print(self.cnt)
self.lbl.setText(str(self.cnt))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mw = main_window()
mw.show()
sys.exit(app.exec_())
通过使用 QtGui.QApplication.processEvents()
方法或 QTimer
类,我们可以解决 PyQt 4 UI 冻结的问题,并确保 GUI 界面保持响应。