Pygame GUI - 未加载

0 投票
1 回答
945 浏览
提问于 2025-04-17 18:02

基本上,我为我的游戏创建了一个pygame菜单,当我点击菜单里的选项时,它会加载其他pygame窗口。不过,有些功能,比如添加用户,我是用Tkinter这个工具做的。当我在pygame中点击加载这些功能时,Tkinter的界面却没有显示出来。有没有人知道我该怎么解决这个问题,或者我需要添加什么才能让它正常工作呢?

它看起来像是要加载什么东西,但实际上并没有。第一个叫“mathsvaders”的程序加载得很好,因为它是pygame程序,但高分界面是用Tkinter做的,所以没有加载出来:

...
pos = 1
while True:
    #events
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif e.type == pygame.KEYDOWN:
            if e.key == pygame.K_DOWN:
               pos += 1
               if pos > 5:
                   pos = 1
            elif e.key == pygame.K_UP:
               pos -= 1
               if pos < 1:
                   pos = 5
            elif e.key == pygame.K_RETURN:
               if pos == 1:
                   import MathsvadersReal
            elif e.key == pygame.K_RETURN:
               if pos == 2:
                    import Highscore
            elif pos == 5:
                 pygame.quit()
                 sys.exit()

这个表单的代码如下:

import Tkinter import Databaseconnector

class simpleapp_tk(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        def create_widgets(self):
            # create welcome label
            label1 = Tkinter.Label(self, text = "Hello world")
            label1.grid(row = 0, column = 2, columnspan = 4, sticky = 'E')

if __name__ == "__main__":
    app = simpleapp_tk(None)
    app.title('my application')
    app.geometry("250x200")
    app.mainloop()    

相关问题:

1 个回答

3

当你导入第二个模块时,其实并没有执行 if __name__ == "__main__": 这一部分。这句话的意思就是:只有当这个文件是你直接运行的主程序时,里面的代码才会执行,而当你导入它时,这部分代码就不会运行。因此,你的 Tk 应用和主事件循环都没有被创建,这样 Tk 相关的代码就无法正常工作,你的图形界面也就不会显示出来。

不过,在你尝试通过把代码放到一个函数里并调用它来解决这个问题之前,你要知道,不能直接从 pygame 的主循环中调用 tkinter 的主事件循环,因为这样的话,pygame 的循环会被阻塞,直到 tkinter 的应用退出。

我觉得你这里的困惑在于,你把模块、脚本、进程和其他一些东西混淆了,统统叫做“程序”。下面我会简单解释一下它们之间的区别。

如果你真的想这样做,有几种可能的解决方案:

  • pygame 可以与任何你想要的事件循环一起工作,只要你正确连接它们。这意味着你可以创建一个顶层的 tkinter 应用,并在其下运行 pygame 的代码。
  • 你可以保留现有的 pygame 循环,并在另一个线程中运行 tkinter 的循环。
  • 你可以把 tkinter 的部分代码重写成使用 pygame 的 GUI 工具包
  • 如果你真的想把每个模块当作“运行一个程序”来处理,像你描述的那样,实际上可以这样做:使用 subprocess 来启动 sys.executable,并把其他脚本作为第一个参数传入。

highscore.py 这样的 Python 文件可以作为脚本运行,也可以作为模块导入。这两者在某些方面是相似的,但在其他方面又不同。

你可以通过在 DOS/bash/其他终端中输入 python highscore.py 来作为脚本运行它(或者在另一个程序中使用类似 subprocess.Popen(sys.executable, 'highscore.py') 的方式)。这会启动一个新的进程,运行 Python 解释器,执行 highscore.py 中的代码,然后退出。这不会影响其他进程,因为你的操作系统知道如何同时运行多个进程。在执行 highscore.py 的代码时,__name__ 会被设置为 "__main__"

你可以通过在一个正在运行的 Python 程序中执行 import highscore 来将其作为模块导入。这并不会启动一个新的进程,而是直接在现有的 Python 程序中执行 highscore.py 的代码,然后继续执行下一行。在执行 highscore.py 的代码时,__name__ 会被设置为 "highscore"

无论是哪种方式,所有顶层模块的代码都会被执行,包括定义类和函数,以及你写的其他语句。你使用 if __name__ == "__main__": 这个检查,是为了在你的文件作为脚本运行时执行额外的代码,而在作为模块导入时不执行这些代码。


还有一点值得注意的是,你的代码中有这一段:

 elif e.key == pygame.K_RETURN:
    if pos == 1:
         import MathsvadersReal
    elif e.key == pygame.K_RETURN:
     if pos == 2:
        import Highscore
    elif pos == 5:
     pygame.quit()
     sys.exit()

如果这就是你实际的缩进,那么 elif e.key == pygame.K_RETURN 将永远为真,所以这个判断是多余的,并且你根本无法到达 elif pos == 5:,所以没有办法退出。

撰写回答