同时运行2个python窗口

同时运行2个python窗口,python,multithreading,tkinter,pygame,Python,Multithreading,Tkinter,Pygame,我正在创建一个游戏应用程序,它有一个菜单窗口,然后是一个单独的游戏窗口。我正在尝试使用Tkinter窗口作为游戏的菜单和pygame窗口,但是如果游戏正在运行,我无法使用菜单(甚至无法关闭它)。如果我尝试,我会收到一条致命错误消息: Fatal Python error: PyEval_RestoreThread: the function must be called with the GIL held, but the GIL is released (the current Python

我正在创建一个游戏应用程序,它有一个菜单窗口,然后是一个单独的游戏窗口。我正在尝试使用Tkinter窗口作为游戏的菜单和pygame窗口,但是如果游戏正在运行,我无法使用菜单(甚至无法关闭它)。如果我尝试,我会收到一条致命错误消息:

Fatal Python error: PyEval_RestoreThread: the function must be called with the GIL held, but the GIL is released (the current Python thread state is NULL)
Python runtime state: initialized

Current thread 0x00002afc (most recent call first):
  File "c:\Users\James\Documents\6th form\comp sci\NEA- A Level\code\gametst.py", line 12 in main
  File "c:\Users\James\Documents\6th form\comp sci\NEA- A Level\code\Menu.py", line 15 in chess
  File "C:\Users\James\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1884 in __call__
  File "C:\Users\James\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1421 in mainloop
  File "c:\Users\James\Documents\6th form\comp sci\NEA- A Level\code\Menu.py", line 22 in <module>
游戏:

有没有办法让我可以同时使用菜单和游戏?谢谢你的帮助


此外,如果您知道将游戏导入菜单的更好方法,那就太好了,尽管您可以尝试在另一个过程中启动游戏。这样一来,
pygame
就不会知道
tkinter
已经启动了它。您可以尝试以下方法:

#menu.py
从tkinter进口*
从子流程导入Popen
从系统导入标准输入、标准输出、标准输出
window=Tk()
窗口几何(“200x200”)
def():
proc=Popen(“python game.py”,stdin=stdin,stdout=stdout,stderr=stderr,shell=True)
按钮=按钮(窗口,text=“button”,命令=f)
button.pack()
window.mainloop()
以及:

#game.py
#请注意,这不在函数中。
导入pygame
pygame.init()
WIN=pygame.display.set_模式((200200))
运行=真
运行时:
pygame.display.update()
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
运行=错误
pygame.quit()
问题是,如果你在空闲状态下启动它,它将不起作用。因此,要解决这个问题,请删除stdin=stdin、stdout=stdout、stderr=stderr,它应该可以工作


使用这种方法,您将无法在
menu.py
game.py
之间发送任何数据。您唯一能做的就是调用
proc\u still\u alive=(proc.poll()==None)
查看进程是否仍然处于活动状态。为此,您需要将
proc
设置为全局变量。

您可以在线程中运行
pygame
部分:

game.py
导入pygame
def main():
pygame.init()
WIN=pygame.display.set_模式((200200))
运行=1
运行时:
pygame.display.update()
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
运行=0
pygame.quit()
打印(“pygame完成”)
def terminate():
如果pygame.get_init():
pygame.event.post(pygame.event.event(pygame.QUIT))
请注意,我添加了用于停止
pygame
循环的
terminate()
函数

menu.py
从tkinter导入*
进口游戏
WIN=Tk()
WIN.geometry(“200x200”)
def():
导入线程
#在线程中执行pygame内容
threading.Thread(target=game.main).start()
按钮=按钮(WIN,text=“button”,command=f)
button.pack()
WIN.mainloop()
game.terminate()#终止pygame循环

我认为如果您尝试在Pygame中构建整个UI,您的境况会好得多。或者在单独的线程中运行
Pygame
部分就足够了,您编译代码了吗?我想如果你把它们都编译成.exe,然后运行它,那就没问题了。@James.L如果你只运行
main()
,而不运行其他任何东西,它还会产生问题吗?@TheLizzard如果他只运行
main()
,就没有菜单可以冻结,在我看来,
main()
使用它的
循环阻塞
WIN.mainloop()
时,实际上它是不可见的,但是他可以尝试使用
after()
循环来运行pygame,不是吗?注意
.poll()
在进程仍在运行时返回
None
。所以
has_proc_ended=proc.poll()不是None,应该使用
。@acw1668您是对的。谢谢你的建议。下次请随意编辑:D。我想我的大脑已经死亡。这太棒了,谢谢!但是你知道有没有办法检查游戏窗口是否在菜单上运行?这是因为当你在游戏运行时按下按钮,它会停止响应。我尝试使用terminate函数,但它仍然停止响应。更不用说,我使用了
is\u alive()
函数。谢谢你的帮助
from tkinter import *
import game

WIN = Tk()
WIN.geometry("200x200")

def f():
    game.main()

button = Button(WIN, text="button", command=f)
button.pack()

WIN.mainloop()
def main():
    import pygame
    pygame.init()

    WIN = pygame.display.set_mode((200, 200))

    run = 1
    while run:
        pygame.display.update()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = 0
                pygame.quit()