在线程中使用pyGame

7 投票
5 回答
11852 浏览
提问于 2025-04-15 23:32

我想把一个pyGame程序作为另一个程序的一部分来使用。使用下面的代码时,pyGame似乎没有处理事件;它对按下'q'键没有反应,也没有显示窗口的标题栏。如果不把go()作为线程运行,它就能正常工作。这是在OSX系统下,我不确定这是不是问题所在。

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()

5 个回答

5

最好在主线程中处理事件和图形。有些环境不太喜欢你从其他线程进行绘图,也有些环境不喜欢你尝试从其他线程处理事件队列。

你想做的事情可能根本无法实现,因为你运行的程序可能对消息队列和你要绘制的窗口有自己的管理方式。

6

这可能有点不太靠谱,但你可以试着确保在进入线程后再导入Pygame。问题可能出在你在一个线程中导入Pygame,然后在另一个线程中使用它。不过,在多个线程中导入也可能会出现其他问题。特别是,一旦你启动了Pygame线程,要确保等它导入完成后再做任何可能导致Python程序关闭的事情,否则你可能会遇到死锁的情况。

8

Pygame 这个库不支持多线程,也就是说它的事件循环必须在主线程中运行!否则,你描述的问题就可能会出现。

一个解决办法是从主线程中调用 pygame.mainloop()

不过,可能你还在用其他模块,它们也需要在主线程中运行。在这种情况下,有一个比较“python风”的解决方案。你可以给 pygame 的主循环加一个参数,这个参数的意思是:只运行主循环几秒钟。因此,你可以创建一个生成器,让主循环运行 0.1 秒,然后定期从主线程调用它。例如:

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

然后只需定期从主线程调用 continue_pygame_loop()

Tkinter 也有同样的问题,但它没有办法指定 runloop() 的超时时间。对我来说,这就是为什么我觉得 pygame 很棒的原因!

撰写回答