Для моего проекта в качестве главного меню у меня есть окно Tkinter, из которого можно запустить окно Pygame. В окне pygame симуляция выполняется с условным бесконечным основным l oop. Я хочу иметь функцию остановки, чтобы пользователь мог закрыть окно pygame и иметь возможность начать новое, однако, если я вызываю pygame.quit()
(или sys.exit()
или pygame.display.quit()
) в программе pygame, оно закрывается а также окно Tkinter, которое я хотел бы оставить открытым.
Я попытался встроить программу pygame в окно Toplevel
, но после того, как я остановил основной pygame l oop и вызвал destroy()
в окне Toplevel
оно закрывается, но основное окно Tk зависает и не будет реагировать на любые действия пользователя, но выполнение кода продолжается после вызова destroy()
.
Pygame
Main l oop
def run(self):
while not self.exit_flag:
self.display.fill(GREY)
self.draw_text()
self.draw_obstacles()
self.pygame_event_check() # a method for checking if event.type == pygame.QUIT
if self.running: #self.running is for pausing the window
if self.counter >= self.lifespan: # create new generation for simulation
self.counter = 0
new_generation, finished = self.rocket_pop.selection()
self.rocket_pop = Population(new_generation)
time.sleep(1)
self.gen_count += 1
if finished > 0 and self.reached_goal == False: # tracking the first generation to reach the goal
print(f"Reached the goal in {self.gen_count} generations")
self.reached_goal = True
for rocket in self.rocket_pop.population: # runs the update method on all individuals
rocket.update(self.counter)
self.counter += 1 # keeping track of the lifetime of the rockets
self.clock.tick(self.fps)
pygame.draw.circle(self.display, PINK, self.target, 20) # draw the goal
pygame.display.update()
print("exit")
Процедура запуска моделирования
def run():
main = Main()
mThread = threading.Thread(target=main.run) # I get a "PyEval_RestoreThread: NULL tstate" error if I just call main.run()
mThread.start()
mThread.join()
Tkinter
Настройка
import tkinter as tk
from genetic_stuff import *
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master=master)
self.master = master
self.pack()
self.setup()
def setup(self):
start = tk.Button(self.master, text="Start", command = self.run_simulation)
stop = tk.Button(self.master, text="Stop", command = self.stop_simulation)
start.place(x=10, y=10, w=100, h=45)
stop.place(x=240, y=10, w=100, h=45)
...
root = tk.Tk()
app = Application(master=root)
app.mainloop()
Запуск / останов симуляции
def run_simulation(self):
self.sim_window = tk.Toplevel(self.master)
embed = tk.Frame(self.sim_window, width = Main.window_width, height = Main.window_height)
embed.pack()
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
os.environ['SDL_VIDEODRIVER'] = 'windib'
run()
self.sim_window.update()
def stop_simulation(self):
Main.exit_flag = True
self.sim_window.destroy()
self.sim_window.update()
ссылки на вставки полного кода для репликации:
фото для справки: