在PyQt中使用定时器时奇怪的Python行为

0 投票
1 回答
679 浏览
提问于 2025-05-01 03:50
import sys

from PyQt4 import QtGui
from PyQt4.QtCore import QObject, QBasicTimer


class Example(QObject):

    def timerEvent(self, event):
        print "timer event, timer Id:", event.timerId()



def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    timer = QBasicTimer()
    timer.start(500, ex) 
    print timer

    timer = QBasicTimer()
    timer.start(300, ex) 
    print timer

    sys.exit(app.exec_())

#Run it
main()

根据这段代码,我本来期待看到两种不同的输出,它们的计时器ID应该不一样。但实际输出是:

<PyQt4.QtCore.QBasicTimer object at 0xb69b90>
<PyQt4.QtCore.QBasicTimer object at 0xb69c08>
timer event, timer Id: 33554433
timer event, timer Id: 33554433
timer event, timer Id: 33554433
timer event, timer Id: 33554433
timer event, timer Id: 33554433
timer event, timer Id: 33554433

还有一个奇怪的地方是,如果我把第二个计时器的变量名改成这样:

    timer = QBasicTimer()
    timer.start(500, ex) 
    print timer

    timer2 = QBasicTimer()
    timer2.start(300, ex) 
    print timer2

那么我就得到了预期的结果:

<PyQt4.QtCore.QBasicTimer object at 0x17b3b90>
<PyQt4.QtCore.QBasicTimer object at 0x17b3c08>
timer event, timer Id: 16777218
timer event, timer Id: 1
timer event, timer Id: 16777218
timer event, timer Id: 16777218
timer event, timer Id: 1
timer event, timer Id: 16777218
timer event, timer Id: 1
timer event, timer Id: 16777218
timer event, timer Id: 16777218
timer event, timer Id: 1

我正在学习Python,这让我感到很困惑。是什么导致了这种情况?变量的名字怎么会影响程序呢?

暂无标签

1 个回答

1

我不明白你为什么觉得这个行为奇怪。事情的顺序就是这样:

ex = Example()
# timer(1) object is created
timer = QBasicTimer()
# ex object registers timer(1)
timer.start(500, ex) 
print timer

# timer(2) object is created
# timer(1) object is destroyed
# timer(1) destructor unregisters timer(1)
timer = QBasicTimer()
# ex object registers timer(2)
timer.start(300, ex) 
print timer

# event loop starts, 300ms later, timer(2) event is processed...
sys.exit(app.exec_())

这只是普通的Python垃圾回收在起作用。创建一个同名的第二个对象会移除对第一个对象的唯一引用,这样第一个对象就会立即被垃圾回收。而且,第二个对象不会被垃圾回收,因为事件循环阻止了函数的返回。

如果你没有阅读关于QBasicTimer的文档,我想你可能会认为这一行:

timer.start(500, ex)

会让ex成为timer的父对象,从而保持它的存活。但要让这个成立,QBasicTimer必须是QObject的子类——而实际上它并不是。

其实,QBasicTimer.start()方法等同于这个:

def start(self, msec, obj):
    self.stop()
    if obj is not None:
        self.id = obj.startImer(msec)

撰写回答