我在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有什么问题吗?
答案 0 :(得分:1)
print self
中的{p> update_not_working
和print 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;