[英]How to subclass Clock in Pyglet?
I want to subclass Clock class of pyglet.clock module, but I have some troubles when I use schedule_interval: 我想对pyglet.clock模块的Clock类进行子类化,但是当我使用schedule_interval时遇到一些麻烦:
The following code doesn't print anything and the object c looks like if not ticked at all: 以下代码不输出任何内容,并且如果根本不打勾,则对象c看起来像:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
class Test(object):
def update(self, dt):
print dt
w = pyglet.window.Window()
@w.event
def on_draw():
w.clear()
t = Test()
c = pyglet.clock.Clock()
c.schedule_interval(t.update, 1/60.0)
pyglet.app.run()
But the next works fine. 但是下一个工作正常。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
pyglet.clock.set_default(self)
class Test(object):
def update(self, dt):
print dt
w = pyglet.window.Window()
@w.event
def on_draw():
w.clear()
t = Test()
c = Clock()
c.schedule_interval(t.update, 1/60.0)
pyglet.app.run()
The only difference is the pyglet.clock.set_default(self) sentence in the constructor method of Clock. 唯一的区别是Clock的构造方法中的pyglet.clock.set_default(self)句子。
I think this is not clear or, at least, is not the best way of subclassing pyglet.clock.Clock to have your own derived Clock class. 我认为这还不清楚,或者至少不是将pyglet.clock.Clock子类化以拥有自己的派生Clock类的最佳方法。
The questions: 问题:
There is some way to set the default clock automatically with Pyglet? 有一些方法可以用Pyglet自动设置默认时钟吗?
There is a solution more elegant or pythonic? 有没有更优雅或Pythonic的解决方案?
Is possible do this without the pyglet.clock.set_default(self) line? 可能没有pyglet.clock.set_default(self)行吗?
I haven't used pyglet, but here's my guess: 我还没有使用pyglet,但这是我的猜测:
You're almost there. 你快到了。 The reason your first implementation probably didn't work is because of these lines: 您的第一个实现可能无法正常运行的原因是由于以下几行:
c = pyglet.clock.Clock()
c.schedule_interval(t.update, 1/60.0)
Here, you are creating a new Clock instance and are scheduling a callback on it. 在这里,您正在创建一个新的Clock实例,并计划对其进行回调。 However, at no point are you actually associating that instance of a clock with pyglet. 但是,实际上您实际上并没有将该时钟实例与pyglet相关联。 So, when you run... 所以,当你跑步...
pyglet.app.run()
...you never actually told pyglet about the new clock instance c
. ...您从未真正告诉pyglet新的时钟实例c
。 Instead, pyglet will use an instance that it made itself. 取而代之的是,pyglet将使用自己创建的实例。 Check out this source code for pyglet from the clock module ...: 从时钟模块中查看pyglet的源代码 ...:
# Default clock.
_default = Clock()
def set_default(default):
'''Set the default clock to use for all module-level functions.
By default an instance of `Clock` is used.
:Parameters:
`default` : `Clock`
The default clock to use.
'''
global _default
_default = default
def get_default():
'''Return the `Clock` instance that is used by all module-level
clock functions.
:rtype: `Clock`
:return: The default clock.
When pyglet starts up, it creates its own instance of the clock (called _default
). pyglet启动时,它将创建自己的时钟实例(称为_default
)。 If you want to use your own, you need to use set_default()
to replace it. 如果要使用自己的,则需要使用set_default()
来替换它。 Therefore, to fix your first piece of code, you probably would need to do one of the following: 因此,要修复第一段代码,您可能需要执行以下操作之一:
c = pyglet.clock.get_default()
c.schedule_interval(t.update, 1/60.0)
...or... ...要么...
c = pyglet.clock.Clock()
pyglet.clock.set_default(c)
c.schedule_interval(t.update, 1/60.0)
The second example above is pointless: pyglet already gives you an instance of Clock, so you'd really just duplicating something that pyglet has already done for you. 上面的第二个例子毫无意义:pyglet已经为您提供了Clock的实例,因此您实际上只是在复制pyglet已经为您完成的工作。 Either way though, you end up scheduling the callback on the clock that pyglet is using . 无论哪种方式,您最终都会在pyglet使用的时钟上安排回调。
So, it should now make sense that, yes, you do need to call set_default()
. 因此,现在应该说是的,您确实需要调用set_default()
。 This is how you tell pyglet to use your object rather than the one it makes by default. 这就是告诉pyglet使用对象而不是默认情况下创建的对象的方式。 Now, you could conceivably put this set_default()
call where you currently have it (in the constructor). 现在,你可以想见,把这个set_default()
调用,你现在有它(在构造函数)。 However, it probably makes more sense to do this... 但是,这样做可能更有意义...
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
...
c = Clock()
pyglet.clock.set_default(c)
Edit : 编辑 :
In response to the question of why you would do this outside the constructor: 为了回答为什么要在构造函数之外执行此操作:
First, as a general rule of thumb, a constructor should only be used to construct the object. 首先,作为一般经验法则,仅应使用构造函数来构造对象。 By adding set_default, you are not only constructing the object, you are also changing the state of some other entity (the pyglet.clock module). 通过添加set_default,您不仅在构造对象,还在更改其他实体(pyglet.clock模块)的状态。 This can cause confusion, as I will show below. 如下所述,这可能会引起混乱。 Assume I wrote code that looked like this... 假设我写的代码看起来像这样...
c = MyClock()
c2 = UnpausedClock()
In this example, I have previously implemented two different clock types: NewClock
and UnpausedClock
. 在此示例中,我以前实现了两种不同的时钟类型: NewClock
和UnpausedClock
。 UnpausedClock
will only consider time to be passing when the game is unpaused. UnpausedClock
仅在游戏未暂停时才考虑时间流逝。 If I put set_default()
in the constructor of these two new classes, then UnpausedClock
would become the new default clock (which I don't want). 如果我将set_default()
放在这两个新类的构造函数中,则UnpausedClock
将成为新的默认时钟(我不想要)。 By NOT putting set_default()
in the constructor, and instead doing the following: 通过不将set_default()
放在构造函数中,而是执行以下操作:
c = MyClock()
c2 = UnpausedClock()
pyglet.clock.set_default(c)
My code is more explicit, and less confusing. 我的代码更加明确,也减少了混乱。
Of course, the code will work either way, but I feel that having the set_default OUTSIDE the constructor gives you more flexibility to use the class as you need to later on. 当然,代码将以任何一种方式工作,但我认为拥有set_default OUTSIDE构造函数可为您提供更大的灵活性,以便以后使用该类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.