使用Tkinter和pygame一起需要注意什么?

8
我正在使用pygame编写程序,需要一些GUI配置文本字段和控制按钮。我已经使用pygame制作了按钮,但是我无法使用pygame编写文本字段。也许我需要将tkinter与pygame一起使用。
如果没有办法在一个窗口中将pygame部分和tkinter部分结合起来,那么我可以将它们放入两个单独的窗口中。
我希望tkinter部分可以更新我的pygame部分的全局变量,这样会有问题吗?我可能会从pygame部分创建一个tkinter子进程,以便tkinter部分可以“看到”pygame部分的全局变量并进行修改。
我能做到这点吗?有什么要注意的地方吗?
3个回答

9
无论是Tkinter还是Pygame都有自己的事件循环,因此想要做到你想要的并不简单。问题在于Pygame想要控制屏幕和用户输入到计算机中的事件。这与GUI库的要求相冲突,它们也想“掌控一切”。
我建议继续使用Pygame,它有一些不错的GUI工具包可以帮助您创建按钮和其他控件。参见此页面 - 它应该可以澄清问题。您还可以在这个讨论中找到有用的信息。
除了实际的方面,使用Pygame创建的GUI对于游戏而言也更加适合,因为游戏通常有原创的、主题化的用户界面,而不是我们在其他应用程序中习惯的平淡无奇的“文本框+按钮”窗口。
请查看Pygame wiki上的一些示例游戏,其中许多都有GUI,您可以从中借鉴想法和代码。

1
Pygame没有事件循环 - 它期望你编写自己的事件循环 - 因此,从pygame应用程序内部创建Tkinter应用程序是可以的,除非使用pygame的全屏模式。但是你是对的,用户应该为pygame使用一些工具包。 - jsbueno
@jsbueno:一旦你调用Tkinter,它的事件循环便会掌控程序。那么在正在运行的pygame循环中如何运行它? - Eli Bendersky
PGU工具包很糟糕。没有教程,我只能自己摸索。现在我认为它正在工作,但突然间窗口无缘无故地冻结了,也没有任何异常提示。 - lamwaiman1988

3
    from tkinter import *
    import pygame
    import random
    import os
    global playing
    playing=False
    def playpause():
        global playing
        if playing==True:
            playing=False
        else:
            playing=True
    root = Tk()
    embed = Frame(root, width=640, height=480)
    embed.grid(row=0,column=2)
    playpausebutton=Button(root, command=playpause, text="Play/Pause")
    playpausebutton.grid(row=1,column=2)
    root.update()
    os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
    os.environ['SDL_VIDEODRIVER'] = 'windib'
    pygame.display.init()
    screen = pygame.display.set_mode((640,480))
    pygame.display.flip()
    while True:
        #your code here
        if playing: 
                screen.fill((random.randint(0,255),random.randint(0,255),random.randint(0,255)))
        pygame.display.flip()
        root.update()

这个方法非常有效,我已经在多种情况下成功使用过。


这对我有效。唯一遇到的问题是,我必须注释掉设置视频驱动程序为“windib”的那一行,否则pygame会报错说“没有可用的视频设备”。(我退出时也会收到投诉,但这并不是真正的问题。) - hosford42
我提交了一个编辑来解决退出时的错误和警告。我还添加了一个调用root.update_idletasks(),因为这通常由主循环调用。 - hosford42

1
我也发现pgu很糟糕。然而,你所说的tkinter事件循环接管的观点是错误的。你只需要调用root.update而不是mainloop,并将其放在while循环中替换mainloop即可。然而,回答你的主要问题,有一件事情你应该知道。每当我同时运行这两个程序时,就会出现以下回溯信息:
TclError: expected boolean value but got "-1"
致命的Python错误:(pygame降落伞)段错误
此应用程序已请求终止它的运行方式。请联系应用程序的支持团队获得更多信息。
因此,我会避免组合使用,尽管我怀疑这个特定问题可能涉及我的线程使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接