2014-11-02 61 views
0
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() 

使用此代码我期望看到2种不同类型的输出,它们在计时器ID上有所不同。但输出是:在pyqt中使用计时器时奇怪的Python行为

<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

我不知道你为什么会认为这种行为很奇怪。事件的顺序就是这样:

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) 

将使extimer父,因此保持它活着。但要做到这一点,QBasicTimer必须是QObject的子类 - 事实并非如此。

QBasicTimer.start()方法实际上是相同的:

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

我读了'QBasicTimer'的文档,但没有关于实施只字不提。我有点害怕,想到我应该在哪里得到这个想法,还有什么其他神秘的问题等着我。无论如何,这真的很奇怪,计时器在执行过程中被破坏。 – 2014-11-02 21:37:53

+0

@LeNoob。你不需要理解实现:我只是想解释发生了什么。但我仍然感到惊讶,你认为这是“神秘”的。你是Python的新手,还是仅仅是PyQt?定时器在“执行的中间”没有被破坏,因为在事件循环开始之前什么都不会发生(就事件而言)。无论如何,它是Qt计时器设计的一部分,它们在删除时会自动停止。这对你来说似乎不合理吗? – ekhumoro 2014-11-03 01:03:45

+0

我对Python比较陌生,对PyQt也是全新的:)我主要是Java开发人员,我明显遇到了抓内部Python的问题,在这种情况下,垃圾收集是如何工作的(更不用说线程这里了)。我试图阅读文档和东西,但我根本无法理解它。 – 2014-11-29 23:53:10