简体   繁体   English

如何在Pyglet中子类化Clock?

[英]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 . 在此示例中,我以前实现了两种不同的时钟类型: NewClockUnpausedClock 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM