【问题标题】:closeEvent and QMessageBox seems to block updating UIcloseEvent 和 QMessageBox 似乎阻止更新 UI
【发布时间】:2013-12-23 08:36:21
【问题描述】:

我已经收到这个问题好几个小时了。我调查了很多事情(我什至创建了一个自定义 QDialog),但现在我确定是 closeEvent 和 QMessageBox 组合导致了这个问题。我想知道是否有什么方法可以让我克服这个问题?

问题

我想让我的代码在关闭之前清理所有使用的资源,例如线程、DLL 等。实际完成整个清理工作需要几秒钟。为了确保用户应用程序运行正常,我想“打印”一条状态消息,确认应用程序正在尝试清理其资源。

但是,使用下面的代码,我只能得到“你确定.....”。 “正在停止应用程序.....”消息未插入到 processEdit

我的代码sn-p,test.py:

import sys, os, time
from PySide.QtGui import *
from PySide.QtCore import *
from time import sleep

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(350, 100, 300, 300)
        self.processEdit = QTextEdit()
        self.grid = QGridLayout()
        self.grid.addWidget(self.processEdit, 0, 0)
        self.setLayout(self.grid)
        self.show()

    def closeEvent(self, event = False):
        self.processEdit.insertHtml("\n\n Are you sure.....")
        if isinstance(event, QCloseEvent):
            event.ignore()
        confirm = QMessageBox.question(self, 'Message', "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if confirm == QMessageBox.Yes:
            self.processEdit.insertHtml("\n\n Stopping App.....")

            # clean up resources and status reports here.
            time.sleep(5) # only here for the snippet

            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':

    qapp = QApplication(sys.argv)
    c = MainWindow()
    sys.exit(qapp.exec_())

【问题讨论】:

    标签: python pyside qmessagebox


    【解决方案1】:

    文本已正确插入。但是,问题是您通过在 closeEvent 回调内部执行睡眠/清理来阻止事件循环。由于 UI 更新使用事件系统,因此在关闭应用程序之前不会处理下一个绘制事件。

    在 PyQt(没有 PySide)中,我能够解决这个问题

    self.processEdit.insertHtml("\n\n Stopping App.....")
    
    event.accept()
    
    self.repaint()
    qapp.processEvents()
    
    # clean up resources and status reports here.
    time.sleep(5) # only here for the snippet
    

    但我认为这是不好的做法(不仅因为访问全局变量)。您应该尝试保持 GUI 响应,即使在关机期间也是如此。见here

    【讨论】:

    • 重绘是多余的,可以用QtGui.qApp访问应用实例。我同意在关机期间让 GUI 无响应不是一个好主意 - 也许最好隐藏窗口和/或显示启动画面。
    • 太棒了。我不知道repaint() 功能。我确实计划确保 GUI 始终响应。睡眠只是一个.. 嗯.. 有事可做.. 在 sn-p 上。哈哈再次感谢。
    • @kazemakase 我已经接受了你的回答,但我想知道你是否可以跟进你所说的; “通过在 closeEvent 回调中执行睡眠/清理来阻止事件循环”。在终止应用程序之前还有其他地方可以进行清理吗? (应该早点问这个,但我很高兴它起作用了)。 (嗯..我应该在另一个问题上问这个吗o_O)
    • 当程序在事件处理程序中时,不能处理其他事件。插入对 qapp.processEvents() 的调用实际上是一种 hack,可确保处理重绘事件。发生的情况是在关闭事件仍在处理时开始了一轮事件处理。您可以尝试拆分对 sys.exit() 和 qapp.exec_() 的调用。 qapp.exec_() 阻塞,直到程序完成。之后,您可以进行清理。这样,当你的清理代码被执行时,GUI 就已经关闭了。
    猜你喜欢
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多