40

is there a way to detect if user trying to close window? For example, in Tkinter we can do something like this:

def exit_dialog():
    #do stuff
    pass

root = Tk()
root.protocol("WM_DELETE_WINDOW", exit_dialog)
root.mainloop()

Thanks.

SaulTigh
  • 913
  • 2
  • 14
  • 27

2 Answers2

104

Override the closeEvent method of QWidget in your main window.

For example:

class MainWindow(QWidget): # or QMainWindow
    ...

    def closeEvent(self, event):
        # do stuff
        if can_exit:
            event.accept() # let the window close
        else:
            event.ignore()

Another possibility is to use the QApplication's aboutToQuit signal like this:

app = QApplication(sys.argv)
app.aboutToQuit.connect(myExitHandler) # myExitHandler is a callable
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Oleh Prypin
  • 33,184
  • 10
  • 89
  • 99
  • 7
    Note that this will not work in the main thread is busy calculating. One should move the calculations to another thread to be able to close the window. – d33tah Feb 26 '13 at 22:52
  • 2
    note that on a QMainWindow, there is no attribute `canExit` – Tcll May 06 '15 at 15:43
  • 2
    @Tcll, there is no attribute anywhere in the Qt library (to my knowledge, but definitely not in QWidget or QMainWindow). That is the point: you define it as a custom handler. – Alex Huszagh Jan 07 '16 at 21:27
  • Is it possible to connect `aboutToQuit` from inside a separate file that only subclasses the MainWindow, as is the standard workflow using Qt Designer to define the .ui, pyside-uic to convert that to a .py that you don't manually edit, then this separate file for user implementation of the UI elements? – James Paul Mason Apr 24 '17 at 17:33
6

If you just have one window (i.e the last window) you want to detect then you can use the setQuitOnLastWindowClosed static function and the lastWindowClosed signal.

from PySide2 import QtGui
import sys


def keep_alive():
    print("ah..ah..ah..ah...staying alive...staying alive")
    window.setVisibility(QtGui.QWindow.Minimized)


if __name__ == '__main__':
    app = QtGui.QGuiApplication()
    app.setQuitOnLastWindowClosed(False)
    app.lastWindowClosed.connect(keep_alive)

    window = QtGui.QWindow()
    window.show()

    sys.exit(app.exec_())

Hope that helps someone, it worked for me as on my first attempt I couldn't override closeEvent(), lack of experience!

mcdixon
  • 61
  • 1
  • 3