How to get Tkinter and Pygame windows to run at the same time? [duplicate]

20 hours ago 3
ARTICLE AD BOX

In tkinter you can try to use window.after(millisecond, function) to process Pygame's event (and redraw window) without while True (which is blocking window.mainloop())

OR

In pygame you can try to use window.update() to force tkinter to process events and redraw widgets in windows without window.mainloop() (which is blocing pygame)

This way you will have only one loop and it doesn't need multiprocessing.


But I don't know if problem is also that you destroy and recreate again tkinter window.


I made full working code.

It uses window.after() to keep processing Pygame events when it displays Back button.

It needed to use global variable to control when after() should stop running.

(I uses pg.event.clear() instead of for event in pg.event.get(): pass)

I also create window Tk() only once and later I use withdraw() to hide it and deiconify() to show it again. I also keep buttons in Frame to simpler remove them from window and replace with other Frame with new buttons.

(instead of .destroy() you can also use .pack_forget() and later it needs only .pack() again to show it)

import tkinter as tk import pygame as pg def main(): global window global frame frame = None # create window only once and run mainloop window = tk.Tk() set_frame_main_menu() # at start window.mainloop() def set_frame_main_menu(): global frame if frame is not None: frame.destroy() print("set_frame_main_menu") frame = tk.Frame(window) frame.pack() button1 = tk.Button(frame, text="Start game", command=on_button_run_game) button1.pack() button2 = tk.Button(frame, text="EXIT", command=window.destroy) button2.pack(fill="x") def set_frame_back_button(): global frame if frame is not None: frame.destroy() print("set_frame_back_button") frame = tk.Frame(window) frame.pack() button = tk.Button(frame, text="Back to menu", command=on_button_back_to_main_menu) button.pack() def on_button_run_game(): print("hide tkinter window") window.withdraw() # hide window print("play game") play_game() print("show tkinter window") window.deiconify() # show again window print("set back button") set_frame_back_button() print("keep running Pygame loop") # use after() to run look with pygame events without blocking mainloop global keep_loop keep_loop = True # need to stop looping keep_pygame_event_loop() # start at once # window.after(100, keep_pygame_event_loop) # OR start after 100ms def play_game(): import random pg.init() screen = pg.display.set_mode((100, 100)) clock = pg.time.Clock() while True: color = random.choice(["red", "green", "blue"]) for event in pg.event.get(): if event.type == pg.QUIT: return screen.fill(color) pg.display.flip() clock.tick(5) def keep_pygame_event_loop(): global keep_loop if keep_loop: pg.event.clear() # get all events and do nothing window.after(100, keep_pygame_event_loop) # run again after 100ms else: pg.quit() def on_button_back_to_main_menu(): global keep_loop # stop loop keep_loop = False set_frame_main_menu() main()
Read Entire Article