2013-04-30 3 views
0

Je veux sous-classe classe d'horloge du module pyglet.clock, mais j'ai quelques ennuis quand j'utilise schedule_interval:Comment sous-classer Clock à Pyglet?

Le code suivant n'imprime rien et l'objet c ressemble sinon tic tac du tout:

#!/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() 

Mais les prochaines fonctionne très bien.

#!/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() 

La seule différence est le pyglet.clock.set_default (auto) phrase dans la méthode constructeur de l'horloge.

Je pense que ce n'est pas clair ou, au moins, n'est pas la meilleure façon de subclassing pyglet.clock.Clock d'avoir votre propre classe dérivée de l'horloge.

Les questions:

Il y a un moyen de régler l'horloge par défaut automatiquement Pyglet?

Il y a une solution plus élégante ou pythonique?

est possible le faire sans la ligne de pyglet.clock.set_default (auto)?

+2

Chaque fois que vous dites que quelque chose «fonctionne» ou «ne fonctionne pas», assurez-vous d'être plus précis. Quelque chose qui "ne fonctionne pas" pourrait signifier qu'il commet une erreur, ne fait pas erreur, mais ne fait pas ce que vous attendez, etc. Qu'est-ce qui ne fonctionne pas dans la première section du code? –

+0

@MarkHildreth Merci pour le conseil! Je veux dire, dans le premier code, la mise à jour n'imprime rien et c semble ne pas être cochée, mais je ne sais pas pourquoi ... –

Répondre

1

Je ne l'ai pas utilisé pyglet, mais voici ma conjecture:

Vous y êtes presque. La raison pour laquelle votre première mise en œuvre n'a probablement pas fonctionné est à cause de ces lignes:

c = pyglet.clock.Clock() 
c.schedule_interval(t.update, 1/60.0) 

Ici, vous créez une nouvelle instance de l'horloge et planifiez un rappel à ce sujet. Cependant, à aucun moment vous n'associez réellement cette instance d'une horloge avec pyglet. Donc, lorsque vous exécutez ...

pyglet.app.run() 

... vous a jamais dit en fait pyglet au sujet de la nouvelle instance d'horloge c. Au lieu de cela, pyglet utilisera une instance qu'il a faite lui-même. Regarde ce source code for pyglet from the clock module ...:

# 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. 

Lorsque pyglet démarre, il crée sa propre instance de l'horloge (appelée _default). Si vous voulez utiliser le vôtre, vous devez utiliser set_default() pour le remplacer. Par conséquent, pour fixer votre premier morceau de code, vous auriez probablement besoin de faire une des opérations suivantes:

c = pyglet.clock.get_default() 
c.schedule_interval(t.update, 1/60.0) 

... ou ...

c = pyglet.clock.Clock() 
pyglet.clock.set_default(c) 
c.schedule_interval(t.update, 1/60.0) 

Le second exemple ci-dessus est inutile: pyglet vous donne déjà une occurrence de Clock, donc vous dupliqueriez juste quelque chose que pyglet a déjà fait pour vous. Quoi qu'il en soit, vous finissez par programmer le rappel sur l'horloge que pyglet utilise.

Alors, il faut maintenant donner un sens, oui, vous avez besoin d'appeler set_default(). C'est ainsi que vous dites à pyglet d'utiliser votre objet plutôt que celui qu'il crée par défaut. Maintenant, vous pouvez imaginer mettre cet appel set_default() où vous avez actuellement (dans le constructeur).Cependant, il est probablement plus judicieux de le faire ...

class Clock(pyglet.clock.Clock): 
    def __init__(self): 
     super(Clock, self).__init__() 

... 

c = Clock() 
pyglet.clock.set_default(c) 

Modifier:

En réponse à la question de savoir pourquoi vous faire en dehors du constructeur:

D'abord, comme En règle générale, un constructeur ne devrait être utilisé que pour construire l'objet. En ajoutant set_default, vous construisez non seulement l'objet, mais vous changez aussi l'état d'une autre entité (le module pyglet.clock). Cela peut causer de la confusion, comme je le montrerai plus bas. Supposons que je l'ai écrit le code qui ressemblait à ceci ...

c = MyClock() 
c2 = UnpausedClock() 

Dans cet exemple, je l'ai déjà mis en œuvre deux types d'horloge différentes: NewClock et UnpausedClock. UnpausedClock ne considérera que l'heure de passer lorsque le jeu n'est pas suspendu. Si je mets set_default() dans le constructeur de ces deux nouvelles classes, alors UnpausedClock deviendrait la nouvelle horloge par défaut (que je ne veux pas). En ne mettant pas set_default() dans le constructeur, et au lieu de faire ce qui suit:

c = MyClock() 
c2 = UnpausedClock() 
pyglet.clock.set_default(c) 

Mon code est plus explicite et moins confus.

Bien sûr, le code fonctionnera dans un sens ou dans l'autre, mais je pense que le fait d'avoir SET_DEFAULT OUT du constructeur vous donne plus de flexibilité pour utiliser la classe comme vous le ferez plus tard.

+0

Je veux que la sous-classe Clock fournisse des fonctionnalités supplémentaires à la classe Pyglet Clock. Pour cette raison et clairement dans le code que je choisis, appelez set_default dans le constructeur. Dans ce contexte, pensez-vous que l'appel à set_default est meilleur à l'intérieur ou à l'extérieur du constructeur? –

+0

@SuperUser: Voir ma modification dans ma réponse. –

+0

Merci pour l'explication. Le code que j'écris dans la question n'est qu'un exemple (pas le code de production). Peut-être que je dois vous donner plus d'informations sur le code de mon projet afin que vous puissiez comprendre mon point de vue. Je pense que le constructeur est la meilleure solution car mon objet Clock est un singleton et la méthode constructeur laisse l'horloge dans un état valide (sans cette ligne dans le constructeur l'horloge ne coïncide pas!). –