Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyGame in a thread

I want to use a pyGame program as a part of another process. Using the following code, pyGame doesn't seem to be processing events; it doesn't respond to the 'q' key nor does it draw the titlebar for the window. If go() is not run as a thread, it works fine. This is under OSX; I'm unsure if that's the problem or not.

import pygame, threading, random

def go():
  pygame.init()
  surf = pygame.display.set_mode((640,480))
  pygame.fastevent.init()

  while True:
    e = pygame.fastevent.poll()
    if e.type == pygame.KEYDOWN and e.unicode == 'q':
      return

    surf.set_at((random.randint(0,640), random.randint(0,480)), (255,255,255))
    pygame.display.flip()

t = threading.Thread(target=go)
t.start()
t.join()
like image 939
Dan Avatar asked Jun 03 '10 23:06

Dan


2 Answers

Possibly a long shot, but try making sure you don't import Pygame until you're in the thread. It's just about possible that the problem is that you're importing Pygame on one thread and then using it on another. However, importing on multiple threads can have other issues. In particular, make sure that once you start the Pygame thread you wait for it to finish importing before you do anything that might cause the Python process to shut-down, or you might get a deadlock.

like image 84
Weeble Avatar answered Sep 28 '22 06:09

Weeble


Pygame is not threadsafe and the eventloop is required to run on the main thread! Otherwise, the problem you describe can occur.

One solution is to call pygame.mainloop() from the main thread.

However,maybe you are using other modules that also require running from the main thread. There is in this case one pythonic solution. you have the possibility to run pygame mainloop with an argument. This argument means: run the mainloop for only a few seconds. Hence what you can do is create a generator that runs mainloop for a 0.1 second that you call periodically from main thread. For example:

def continue_pygame_loop():
    pygame.mainloop(0.1)
    yield

then just call continue_pygame_loop() periodically from main thread

Tkinter suffers from the same problem, but has no way to specify runloop() with a timeout. For me, this is why pygame is great!

like image 34
Nath Avatar answered Sep 28 '22 06:09

Nath