closeEvent and QMessageBox seems to block updating UI

273 views Asked by At

I have been getting this issue for hours now. I have investigated a lot of things (I even created a custom QDialog), but now I am determined that it's the closeEvent and QMessageBox combination that causes this problem. What I want to know is if there is any way for me to overcome this problem?

Issue:

I want to allow my code to clean up all its used resources such as threads, DLLs, etc prior to closing. It takes a few seconds to actually do the whole clean up. In order to assure the user that the application is functioning properly, I want to 'print-out' a status message confirming that the application is trying to clean-up its resources.

However, using the codes below all I could get is "Are you sure.....". The "Stopping App....." message is not inserted into processEdit.

My code snippet, 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_())
1

There are 1 answers

4
MB-F On BEST ANSWER

The text is correctly inserted. However, the problem is that you block the event loop by performing sleep/cleanup inside the closeEvent callback. Since the UI updating utilizes the event system the next paint event is not processed before closing the application.

In PyQt (don't have PySide) I was able to work around this issue with

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

But I think this is bad practice (not only because of accessing a global variable). You should attempt to keep your GUI responsive, even during shutdown. See here.