Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

running 2 python windows simultaneously

I'm creating a game app and it has a menu window then a separate game 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). 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

like image 207
James.L Avatar asked Sep 01 '26 14:09

James.L


2 Answers

You can run the pygame part in a thread:

game.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.

menu.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
like image 84
acw1668 Avatar answered Sep 04 '26 02:09

acw1668


Well you can try to start it in another process. That way pygame will have no idea that tkinter has started it. 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. So solve that issue remove the stdin=stdin, stdout=stdout, stderr=stderr and it should work.

With this approach you wouldn't be able to send any data between menu.py and game.py. The only thing you can do is call proc_still_alive = (proc.poll() == None) to see if the process is still alive. For that you will need to make proc a global variable.

like image 30
TheLizzard Avatar answered Sep 04 '26 02:09

TheLizzard



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!