[SOLVED][PYTHON] pygame event handler

Started by
3 comments, last by rmckee78 16 years, 5 months ago
I have just started working with pygame and wrote a simple program that loads a bmp blits it to a surface and then flips the surface. It also has an event handler to print and events other than QUIT (like mouse movements, key presses etc.) Everything works fine except for the event handler. It correctly prints any events but does not handle QUIT correctly. If I click the close box on the window I get the following error:
Quote: Traceback (most recent call last): File "C:/Python24/pygametrial", line 19, in -toplevel- input(pygame.event.get()) File "C:/Python24/pygametrial", line 14, in input sys.exit(0) SystemExit: 0
The event handler code is:

def input(events):
    for event in events:
        if event.type == QUIT:
            sys.exit(0)
        else:
            print event
            
while True:
    input(pygame.event.get())




I am working from this tutorial and a tutorial I found on this site. [Edited by - rmckee78 on November 2, 2007 8:10:08 AM]
Advertisement
That's not actually an error, by the looks of it. That's it quitting.
That's not an error, as Kylotan points out. sys.exit() raises the SystemExit exception, which, since you don't handle it within your program, bubbles up to the operating system.

You have a couple of options. The first is to have a program-global flag indicating running status, which the QUIT exit handle sets to False:
running = Truedef input(events):  for event in events:    if event == QUIT:      running = False    ...while running:  input(pygame.event.get())


This method works, of course, but it introduces an object with no ownership semantics, and thus no access controls - the global flag, running. A second approach avoids this pitfall, but complicates your main loop slightly:
def input(events):  for event in events:    if event == QUIT:      sys.exit(0)    ...while running:  try:    input(pygame.event.get())  except SystemExit:    print "Good bye!"    break


This method works, but now you're going to be instrumenting your main loop to handle all the various exceptions you may raise within your code for non-error purposes. Ugh. Plus, the exception mechanism is being used as a secondary event queue... hey, wait a minute!

The third approach is simply to use the event queue as the main loop:
NULL_EVENT = pygame.event.USEREVENT + 1evt = pygame.event.Event(NULL_EVENT, None)while evt.type != QUIT:  ...


You can make this more robust by using another user-created event type as the loop sentinel, so that your application can respond to a QUIT event, perform some processing, then post your own loop exit event to the queue:
NULL_EVENT = pygame.event.USEREVENT + 1TERMINATE = pygame.event.USEREVENT + 2evt = pygame.event.Event(NULL_EVENT, None)while evt.type != TERMINATE:  ...  if evt.type == QUIT:    # pause game and prompt user. if yes,    # release resources, etc, then     # pygame.event.post(pygame.event.Event(TERMINATE, None))    #  ...


You can do a lot of very powerful things with the PyGame event system. You can maintain rock-solid frame updates and game heartbeat by generating corresponding events using a timer:
pygame.time.set_timer(NULL_EVENT, 1000.0/30) # generate a NULL_EVENT 30 times a second

By using pygame.event.set_blocked, pygame.event.set_allowed and pygame.event.get, you can event priority sort your events, such that screen refreshes, etc, are reliably handled on time. I'm looking into building a preemptive layer on top of this foundation, and I'll share what I find.
I'm running into another problem with it. It seems that sometimes the program will display my events like mouse movements, button presses etc. However sometimes it doesn't register any input and goes into (not responding) and crashes. If I run from the command line the python command line crashes too. If I run from the IDE it does not crash.
Thanks guys. I found I had an indent error and was never actually calling my event handler due to it. Amazingly the backspace key was the answer. Not used to thinking about things the Python way yet, was sure there was some not so obvious C++ like window setup problem.

I messed with the event handler and it looks like this now:

def kill():    pygame.display.quit()    pygame.quit()    returndef main():    pygame.init()    pygame.font.init()    w=320.0    h=200.0    screen = pygame.display.set_mode((int(w*2),int(h)),pygame.SWSURFACE|pygame.DOUBLEBUF,24)#|pygame.FULLSCREEN,24)    pygame.display.set_caption("Trial")    clock=pygame.time.Clock()    #Main loop    while True:        #Event handling        clock.tick(60)        for event in pygame.event.get():            if event.type==QUIT:                kill()                return            if event.type==KEYDOWN:                if event.key==K_ESCAPE:                    kill()                    return                keys[event.key]=True            elif event.type==KEYUP:                keys[event.key]=False                print event        if __name__=="__main__": main()

This topic is closed to new replies.

Advertisement