Search code examples
pythonpyglet

Window shows previous frame when a key is pressed


I've created a simple script that shows a square moving to the left:

import pyglet

window = pyglet.window.Window(800, 600)

x = 0
y = 250
width = 100
height = 100


def update(time):
    global x

    window.clear()
    pyglet.graphics.draw(4, pyglet.gl.GL_QUADS, ('v2f', [x, y, x, y+height, x+width, y+height, x+width, y]))
    x += 10


pyglet.clock.schedule_interval(update, 1/10)

pyglet.app.run()

The square is rendered correctly when there is no keyboard input, but whenever I press a key, it seems like the window is cleared and the previous frame gets rendered again. I solved the problem by splitting the update function and by using the on_key_press() function:

@window.event
def on_key_press(symbol, modifiers):
    draw()


def update(time):
    global x
    x += 10
    draw()


def draw():
    window.clear()
    pyglet.graphics.draw(4, pyglet.gl.GL_QUADS, ('v2f', [x, y, x, y + height, x + width, y + height, x + width, y]))

But I don't think is the right way to solve the problem, because I'm rendering the square two times in one frame. You can see what the problem is over here: https://youtu.be/cIwuLYuLWtY.


Solution

  • In pyglet the window should be redraw in the on_draw(). See also Writing a pyglet application.
    After a event occurs, the on_draw event is executed and the window is updated.
    When no on_draw event is implemented, then it seems that in a double buffered context a buffer swap is triggered after the key event. Since the scene is not updated (because there is nor on_draw), the previous frame is shown.

    I recommend to implement a on_draw event to redraw the window:

    import pyglet
    
    window = pyglet.window.Window(800, 600)
    x, y, width, height = 0, 250, 100, 100
    
    def update(time):
        global x
        x += 10
    
    @window.event
    def on_draw():
        window.clear()
        pyglet.graphics.draw(4, pyglet.gl.GL_QUADS, ('v2f', [x, y, x, y+height, x+width, y+height, x+width, y]))
    
    pyglet.clock.schedule_interval(update, 1/10)
    pyglet.app.run()