简体   繁体   English

同时运行 2 个 python windows

[英]running 2 python windows simultaneously

I'm creating a game app and it has a menu window then a separate game window.我正在创建一个游戏应用程序,它有一个菜单 window,然后是一个单独的游戏 window。 I'm trying to get a Tkinter window to act as the menu and a pygame window for the game however if the game is running, I cant use the menu (can't even close it). I'm trying to get a Tkinter window to act as the menu and a pygame window for the game however if the game is running, I cant use the menu (can't even close it). If I try I get a fatal error message:如果我尝试,我会收到一条致命错误消息:

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>

This is the minimum code to reproduce:这是重现的最少代码:

Menu:菜单:

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

game:游戏:

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

Is there a way to do this so that I can use the menu and the game at the same time?有没有办法让我可以同时使用菜单和游戏? thx for any help谢谢任何帮助

also if you know a better way to import the game to the menu that would be great, not overly bothered about that though另外,如果您知道将游戏导入菜单的更好方法,那将是很棒的,但不要过分担心

You can run the pygame part in a thread:您可以在线程中运行pygame部件:

game.py游戏.py

import pygame

def main():
    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()
    print("pygame done")

def terminate():
    if pygame.get_init():
        pygame.event.post(pygame.event.Event(pygame.QUIT))

Note that I have added terminate() function for stopping the pygame loop.请注意,我添加了terminate() function 以停止pygame循环。

menu.py菜单.py

from tkinter import *
import game

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

def f():
    import threading
    # execute the pygame stuff in a thread
    threading.Thread(target=game.main).start()

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

WIN.mainloop()
game.terminate()  # terminate pygame loop

Well you can try to start it in another process.那么你可以尝试在另一个进程中启动它。 That way pygame will have no idea that tkinter has started it.这样pygame将不知道tkinter已经启动了它。 You can try something like this:你可以尝试这样的事情:

# menu.py
from tkinter import *
from subprocess import Popen
from sys import stdin, stdout, stderr

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

def f():
    proc = Popen("python game.py", stdin=stdin, stdout=stdout, stderr=stderr, shell=True)

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

window.mainloop()

and:和:

# game.py
# Please note this isn't in a function.
import pygame
pygame.init()

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

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

The problem is that it isn't going to work if you start it in IDLE.问题是,如果您在 IDLE 中启动它,它将无法工作。 So solve that issue remove the stdin=stdin, stdout=stdout, stderr=stderr and it should work.因此,解决该问题删除stdin=stdin, stdout=stdout, stderr=stderr并且它应该可以工作。

With this approach you wouldn't be able to send any data between menu.py and game.py .使用这种方法,您将无法在menu.pygame.py之间发送任何数据。 The only thing you can do is call proc_still_alive = (proc.poll() == None) to see if the process is still alive.你唯一能做的就是调用proc_still_alive = (proc.poll() == None)来查看进程是否还活着。 For that you will need to make proc a global variable.为此,您需要将proc设为全局变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM