1
votes

I have a QDialog, where i create a QTimer Object, which triggers every n seconds a function. After closing the Dialog (hitting the x button), the timer is still firing and seems to be not destroyed. How can i stop it? Currently as a workaround i am explicitly calling Qtimer.stop() when entering the closeEvent()?

I would expect that every class-member is deleted, when the Window is closed, even when i call the Deconstructor explicitly, the Qtimer object persists.

from PyQt4 import QtGui, QtCore
import sys



def update():
    print "tick..."

class Main(QtGui.QDialog):

    def __init__(self, parent = None):
        super(Main, self).__init__(parent)


        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(update)
        self.timer.start(2000)

        # scroll area
        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setWidgetResizable(True)

        # main layout
        self.mainLayout = QtGui.QVBoxLayout()


        self.setLayout(self.mainLayout)


    def closeEvent(self, evt):
        print "class event called"
        self.timer.stop()

myWidget = Main()
myWidget.show()
1

1 Answers

4
votes

http://doc.qt.io/qt-5/timers.html

The main API for the timer functionality is QTimer. That class provides regular timers that emit a signal when the timer fires, and inherits QObject so that it fits well into the ownership structure of most GUI programs. The normal way of using it is like this:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateCaption()));
timer->start(1000);

The QTimer object is made into a child of this widget so that, when this widget is deleted, the timer is deleted too. Next, its timeout() signal is connected to the slot that will do the work, it is started with a value of 1000 milliseconds, indicating that it will time out every second.

In C++, the timers are parented to the widget or another QObject, and then their lifespan is tied to the lifespan of the QObject, but it is still good practice to stop a timer when you don't need it. The layouts get parented when you call setLayout. The timer doesn't know its parent so it doesn't get destroyed when the widget gets destroyed. It just sits on the heap, still getting ran by the QApplication event loop.

http://doc.qt.io/qt-5/qobject.html#setParent

So either pass in self to the constructor of the QTimer, or call setParent on the QTimer to set it into the object tree properly.

http://doc.qt.io/qt-5/objecttrees.html

UPDATE: Apparently setParent isn't working in PyQt. Just pass in self in the QTimer constructor.

Hope that helps.