2

I've been trying to put the main event loop in a decorator in the hope that my program would look neater. I have two files, main.py and event_loop_decorator.py.

In event_loop_decorator.py:

import pygame


class EventLoop(object):
    def __init__(self, func):
        self.func = func
        pygame.init()
        print("pygame should have been initialised.")

    def __call__(self):
        while True:
            pygame.time.wait(50)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    break
            self.func()

In main.py:

import pygame
import event_loop_decorator


@event_loop_decorator.EventLoop
def while_in_event_loop():
    pass


if __name__ == "__main__":
    surface = pygame.display.set_mode((200, 100))
    surface.fill((255, 0, 0))
    pygame.display.flip()
    while_in_event_loop()

As you can see, the simple program is intended to just show a little 200*100 window painted red. It works fine, and the exit window button seems to work fine. But after the program is exited, I get the following output and error.

pygame should have been initialised.
Traceback (most recent call last):
  File "C:/Users/ray/Dropbox/Programming/Python/pygame_test/code/main.py", line 50, in <module>
    while_in_event_loop()
  File "C:\Users\ray\Dropbox\Programming\Python\pygame_test\code\event_loop_decorator.py", line 13, in __call__
    for event in pygame.event.get():
pygame.error: video system not initialized

Process finished with exit code 1

We see that the print command in the constructor of the decorator was called, it's the first line in the output. But later in the output we see that apparently "video system not initialised". When I do it without the decorator, everything worked perfectly. By the way, this is the first time I've used decorators.

Any help? Am I doing something wrong with the decorators? Should pygame.init() never be used with decorators?

Ray
  • 7,833
  • 13
  • 57
  • 91

1 Answers1

3

If you take a look at your __call__ function, you will see that when you break, you return to the while loop again. Returning from the function will solve the issue.

def __call__(self):
    while True:
        pygame.time.wait(50)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return
        self.func()
Bartlomiej Lewandowski
  • 10,771
  • 14
  • 44
  • 75