QTimer persists after QMainWindow is closed

610 views Asked by At

I'm having two QMainWindow subclasses, MyWindow and MyTimerWindow. The application initializes and shows a MyWindow instance which does nothing but initialize and show a MyTimerWindow instance. The MyTimerWindow creates a child object QTimer which fires the function printsomething every two seconds.

When I manually close the MyTimerWindow instance by clicking on the X in the titlebar, the printsomething function keeps being executed every two seconds. To my understanding the QTimer instance should be destroyed when I close its parent window. Can someone explain why the QTimer stays alive?

Here is the code:

import sys
from PyQt4 import QtCore, QtGui

class MyWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setWindowTitle("main window")
        self.centralwidget = QtGui.QWidget()
        self.setCentralWidget(self.centralwidget)
        timerwindow = MyTimerWindow(self)
        timerwindow.show()

class MyTimerWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyTimerWindow, self).__init__(parent)
        self.setWindowTitle("timer window")
        self.centralwidget = QtGui.QWidget()
        self.setCentralWidget(self.centralwidget)
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(2000)
        self.timer.timeout.connect(self.printsomething)
        self.timer.start()
    def printsomething(self):
        print("something")

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    returnvalue = app.exec_()
    sys.exit(returnvalue)
2

There are 2 answers

0
ekhumoro On BEST ANSWER

Clicking the X in the titlebar will send a closeEvent to the window. If the window has a parent, it will be hidden, but not deleted.

To ensure that a parented window is deleted when closed, set the WA_DeleteOnClose flag:

    self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

This will also recursively delete all child objects of the window.

0
justengel On

You can always override the close event.

class MyWindow(QtGui.QMainWindow):
    def __init__(self, parent=None)
        super().__init__(parent)
        ...
        self.timerWindow = MyTimerWindow(self)

    def closeEvent(self, event):
        self.timerWindow.close()
        super().__init__(parent)

Or you can always make your timer window a dialog box which is probably the best solution. I believe that the TimerWindow doesn't close automatically because it is a QMainWindow. A QDialog box should automatically be deleted on main window close.