首页 > 解决方案 > pygame.error:视频系统未初始化,使用线程时

问题描述

最近我完成了关于 python 线程的学习,现在尝试在程序中实现它。这是代码:

from threading import Thread
from time import sleep
import pygame as py

py.init()

X,Y = 900, 800
APP = py.display.set_mode((X, Y))
APP = py.display.set_caption("Test")

def exit_app():
    "To terminate program."
    while True:
        for eve in py.event.get():
            if eve.type == py.QUIT:
                py.quit()
                exit()

def update_display():
    "Update pygame window"
    while True:
        sleep(3)
        py.display.update()

if __name__ == "__main__":
    Thread(target=exit_app).start()
    Thread(target=update_display).start()

现在的问题是,在创建线程后我遇到了问题。当我尝试运行代码时,它会毫无问题地执行,但是当代码退出时(即,当我关闭 pygame 窗口时)我会看到如下错误:

$python3 test.py
pygame 2.0.1 (SDL 2.0.14, Python 3.9.4)
Hello from the pygame community. https://www.pygame.org/contribute.html
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/home/cvam/Documents/test.py", line 23, in update_display
    py.display.update()
pygame.error: video system not initialized      

标签: pythonpygamepython-multithreading

解决方案


好的,首先,您似乎正在尝试创建具有无限循环的单独函数来更新屏幕和事件处理,以清除相同的内容,所有这些都可以在一个循环中完成,并且可能是更好的方法相同。[因此我删除了 exit_app 和 update_display 函数,因为它们使用了另外两个无限 while 循环。]

其次,事件处理不需要使用单独的线程,因为事件处理可以在同一个循环中完成,当您使用无限循环为其创建单独的线程时,会导致混淆哪个线程 pygame应在主线程或 THREAD1 上运行。[因此已将其注释掉。]

还将 pygame.init 函数调用和之前在 if name == 'main' 块内的所有其他语句似乎确保它们被执行。同样在线程启动之前放置它们可以确保它们被执行并且 pygame 的东西在线程执行之前被初始化。

还有一些建议-:

  • 代替 time 模块的 sleep 函数,可以使用 pygame 时间模块的类似函数,即pygame.time.delay函数,它存在于 pygame 中,因此更适合使用。

  • 我在使用内置的 exit 和 quit 函数退出 pygame 程序时遇到了很多错误,因此似乎更喜欢使用 python 的 sys 模块的 exit 函数,因为它在大多数情况下会导致更少的错误。

相同的代码应变为-:

# from threading import Thread
# from time import sleep
import pygame
import sys

if __name__ == "__main__":
    pygame.init()

    X,Y = 900, 800
    APP = pygame.display.set_mode((X, Y))
    APP = pygame.display.set_caption("Test")
    
    # # By detecting the events within the main game loop there is no need
    # # to call a separate thread, and the same may not be working since the two
    # # threads the main one and the THREAD1 are both containing infinite loops and pygame
    # # can only take over one at a time.
    # THREAD1=Thread(target=exit_app)
    # THREAD1.start()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit() # sys module's exit method seems to be better and causes less errors at exit
        
        # # Without a delay the window will still not close incase this script is being
        # # used for that purpose by you.
        # pygame.time.delay(3) # Pygame alternative to sleep method of time module https://www.pygame.org/docs/ref/time.html#pygame.time.delay
        pygame.display.update()
        continue
    
    pass

推荐阅读