取消所有未完成的QTimer活动

时间:2011-02-21 21:19:44

标签: qt pyqt

我正在寻找一种在pyqt中设置多个定时函数调用的方法,可以在需要时取消所有挂起的调用。

我正在使用QtCore.QTimer设置函数调用,但我不知道有什么好方法可以取消这些调用。有什么想法吗?



使用QtCore.QTimer.singleShot(1000, self.function)后,我似乎找不到任何取消方法。相反,如果我创建一个QTimer对象列表,我可以阻止它们,但后来我被迫管理一个计时器对象列表(创建,删除,活动等),我想避免。

# Setup a timer object.
timer = QtCore.QTimer(self)
timer.timeout.connect(self.function)
timer.setSingleShot(True)
timer.start(1000)

# To stop the timer object at some later point.
timer.stop()


我还可以管理自己的挂起函数调用队列,如果可能的话我也想避免(为了简单起见)。



这是一些虚拟代码,显示了我想要做的事情:

import sys
from PyQt4 import QtCore

class Test(QtCore.QObject):

    def __init__(self, parent=None):
        QtCore.QObject.__init__(self, parent)


    def addDelayedCall(self, time, function):
        # Do something here.
        pass


    def clearPendingCalls(self):
        print('  Clearing pending function calls.')
        # Do something here.


    def setupCalls(self):
        self.addDelayedCall(500, self.dummy)
        self.addDelayedCall(1000, self.dummy)
        self.addDelayedCall(1500, self.dummy)
        self.addDelayedCall(2000, self.dummy)


    def dummy(self):
        print('dummy just got called.')


if __name__ == '__main__':
    app = QtCore.QCoreApplication(sys.argv)
    test = Test(app)

    QtCore.QTimer.singleShot(0, test.setupCalls)
    QtCore.QTimer.singleShot(1250, test.clearPendingCalls)

    QtCore.QTimer.singleShot(5000, app.quit)            
    sys.exit(app.exec_())

2 个答案:

答案 0 :(得分:4)

我通过直接使用QObject提供的计时器功能提出了解决方案。我怀疑有一个更优雅的解决方案,但这可能适用于我需要的东西。

import sys
from PyQt4 import QtCore


class Test(QtCore.QObject):

    def __init__(self, parent=None):
        QtCore.QObject.__init__(self, parent)

        self.timers = {}


    def timerEvent(self, event):
        function = self.timers.pop(event.timerId())
        self.killTimer(event.timerId())
        function()


    def addDelayedCall(self, time, function):
        timer_id = self.startTimer(time)

        self.timers[timer_id] = function


    def clearPendingCalls(self):
        print('  Clearing pending function calls.')

        while self.timers:
            timer_id, function = self.timers.popitem()
            self.killTimer(timer_id)


    def setupCalls(self):
        self.addDelayedCall(500, self.dummy)
        self.addDelayedCall(1000, self.dummy)
        self.addDelayedCall(1500, self.dummy)
        self.addDelayedCall(2000, self.dummy)


    def dummy(self):
        print('dummy just got called.')




if __name__ == '__main__':
    app = QtCore.QCoreApplication(sys.argv)
    test = Test(app)

    QtCore.QTimer.singleShot(0, test.setupCalls)
    QtCore.QTimer.singleShot(1250, test.clearPendingCalls)

    QtCore.QTimer.singleShot(5000, app.quit)            
    sys.exit(app.exec_())

答案 1 :(得分:2)

您可以从计时器的超时信号disconnect,并在需要时连接回来。一旦断开连接,即使它仍处于活动状态,您也会停止接收来自计时器的任何呼以下是一个小例子:

import sys
from PyQt4 import QtGui, QtCore

class MainForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.button = QtGui.QPushButton("button", self)       
        self.button.resize(100, 30)

        self.connect(self.button, QtCore.SIGNAL('clicked()'), self.on_button_click)

        self.connected = True
        self.timer = QtCore.QTimer(self)
        self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timeout)
        self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timeout_test)
        self.timer.start(1000)

    def on_button_click(self):
        if self.connected:
            self.disconnect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timeout_test)
        else:
            self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timeout_test)
        self.connected = not self.connected

    def on_timeout(self):
        print 'on_timeout'

    def on_timeout_test(self):
        print 'on_timeout_test'

def main():
    app = QtGui.QApplication(sys.argv)
    form = MainForm()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

一旦计时器启动,两个插槽on_timeouton_timeout_test都会被调用,当您单击按钮 on_timeout_test插槽断开连接然后连接回来时,如果按钮。

希望这有帮助,尊重