在Singleton / Borg中调用QTimer时不执行

时间:2016-04-13 08:08:57

标签: python qt pyqt

我在Singleton中使用QTimer实现了一个计时器。 Singleton使用Borg模式实现。如果我在Singleton函数内单次启动QTimer,它将不会被执行。在Singleton之外的函数中的相同调用效果很好。

这是代码:

#!/usr/bin/env python
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication


class Borg():
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state


class Timers(Borg):
    def __init__(self):
        Borg.__init__(self)

    def update_not_working(self):
        QTimer().singleShot(2000, Timers().update_not_working)
        print('update not working')


def update_working():
    QTimer().singleShot(2000, update_working)
    print('update working')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    print('start timer')
    Timers().update_not_working()
    update_working()

    sys.exit(app.exec_())

输出是(没有错误,没有例外):

start timer
update not working
update working
update working
....

为什么一个电话有效,另一个电话无效?我实施Borg或使用QTimer有什么问题吗?

3 个答案:

答案 0 :(得分:1)

print self中的{p> update_not_workingprint Timers()中的update working表示事件循环开始前的Timers对象与以下内容不同:

update not working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>

@classmethod应该在这里提供帮助,因为它允许像在单镜头语句中那样在类上的实例OR上调用方法。

比较:When should I use @classmethod and when def method(self)?

答案 1 :(得分:1)

这实际上只是普通垃圾收集的问题。

如果您在示例中添加一些调试代码,请执行以下操作:

class Timers(Borg):
    def __init__(self):
        Borg.__init__(self)
        print('init:', self)

    def update_not_working(self):
        QTimer().singleShot(1, Timers().update_not_working)
        print('update not working')

    def __del__(self):
        print('deleted:', self)

它将产生如下输出:

start timer
init: <__main__.Timers object at 0x7f194bf53eb8>
init: <__main__.Timers object at 0x7f1940cfdb00>
deleted: <__main__.Timers object at 0x7f1940cfdb00>
update not working
deleted: <__main__.Timers object at 0x7f194bf53eb8>
update working
update working

正如您所看到的,在单次定时器发送Timers信号之前很久就会删除timeout()个实例。当他们删除时,他们的实例方法也会被删除,这会自动将它们与信号断开。这表明Borg模式不会产生真正的单一模式:它只是模仿一个模型的一些行为。

如果您使用真正的单例类,请执行以下操作:

class Timers2(object):
    _instance = None

    def __new__(cls):
        if Timers2._instance is None:
            Timers2._instance = object.__new__(cls)
        return Timers2._instance

    def update_not_working(self):
        QTimer().singleShot(2000, Timers2().update_not_working)
        print('update not working')

您的示例将按预期工作。这是因为只有一个实例,它通过缓存为类属性而保持活动状态。

最后,update_working()成功的原因是因为它是一个全局定义的函数。与class属性一样,这可以确保在脚本完成之前不会收集垃圾。

答案 2 :(得分:0)

double data = (double)e.Parameter;