pyglet on_draw事件在鼠标移动前暂停

0 投票
1 回答
932 浏览
提问于 2025-04-18 09:26

我正在尝试写我的第一个 pyglet 动画,但遇到了一个问题。

我有一个更新函数是从 on_draw 函数中调用的。这个函数本来应该正常工作,但在循环中会随机停下来。如果我开始移动鼠标,它又会继续执行下去。

我看到在2011年这里有一个关于同样问题的提问,但没有相关的答案:(pyglet on_draw 事件只有在鼠标移动时才会发生)

为了让它正常工作,我需要在 on_draw 中不断调用更新函数。

这是两个函数的代码:

def update(zd):
    stripe.y += zd[0]
    stripe._set_rotation(zd[0])

@window.event
def on_draw():
    window.clear()
    window.clear()
    batch.draw()
    try:
        update(next(calc))
    except:
        pass

我从一个包含很多计算的 calc 函数的大循环中获取更新所需的 zd。

1 个回答

1

这里,试试这个代码:

import pyglet
from pyglet.gl import *
from math import radians, cos, sin, degrees, atan2
from time import time

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_LINE_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE)
pyglet.options['audio'] = ('alsa', 'openal', 'silent')
key = pyglet.window.key

class GUI(pyglet.window.Window):
    def __init__(self):
        super(GUI, self).__init__(640,340, caption='My app')
        self.alive = True
        self.keys_down = {}

        imgTexture = pyglet.image.load('/path/to/image.png')
        self.myImage = pyglet.sprite.Sprite(imgTexture)
        self.myImage.x, self.myImage.y = 10, 50 # x,y from bottom left corner

    def render(self, *args):
        pyglet.gl.glClearColor(1, 1, 1, 1)
        self.clear()
        # .. This is where you draw your objects, for instance
        self.myImage.draw()
        self.flip()

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = False

    def on_key_press(self, symbol, modkey):
        self.keys_down[symbol] = time()

    def on_key_release(self, symbol, modkey):
        if symbol in self.keys_down:
            del(self.keys_down[symbol])

    def on_mouse_release(self, x, y, button, modifiers):
        pass

    def on_mouse_press(self, x, y, button, modifiers):
        print(button,'pressed',(x,y))


    def on_mouse_motion(self, x, y, dx, dy):
        pass

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        pass

    def run(self):
        while self.alive:
            event = self.dispatch_events()

            for symbol in self.keys_down:
                if symbol == key.ESCAPE:
                    self.alive = None
                    break
                elif symbol == key.LEFT:
                    pass #Arrowkey Left
                elif symbol == key.RIGHT:
                    pass #Arrowkey Right
                elif symbol == key.UP:
                    pass #Arrowkey Up
                elif symbol == key.DOWN:
                    pass #Arrowkey Down
                elif symbol == 65515:
                    pass # Win key
                else:
                    print(symbol)
            self.render()


if __name__ == '__main__':
    x = GUI()
    pyglet.clock.set_fps_limit(120)
    x.run()

注意,在这段代码中,on_draw()其实并没有被真正调用过。
在传统的 pyglet 代码中,on_draw() 只有在有事件发生时才会被调用,通常你是通过定时器或其他安排好的事件来触发这些事件的,比如移动鼠标就是其中一个事件。

这段代码是对你熟悉的传统 app.run() 的一种手动覆盖。
所以这里有两个主要的功能:

  1. event = self.dispatch_events()
  2. self.render()

第一个功能是从 pyglet 中获取任何事件,这样可以有效释放任何锁,因为即使是空事件也必须被获取。
第二个功能是渲染函数,这就是 on_draw() 通常做的事情,不过我们现在可以随时调用它(或者在我们想要的时候调用)。

我不是专家,但这对你遇到的99%的图形用户界面(GUI)制作都有效,只要你不打算做大型的3D游戏,这样就足够了。

撰写回答