Как закрыть окно Pygame, не закрывая окно Tkinter? - PullRequest
1 голос
/ 13 февраля 2020

Для моего проекта в качестве главного меню у меня есть окно 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()

ссылки на вставки полного кода для репликации:

фото для справки:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...