对于我的项目,我有一个Tkinter窗口作为主菜单,从中可以启动pygame窗口。在pygame窗口中,模拟运行有条件的无限主循环。
我想要一个停止功能,以便用户可以关闭pygame窗口并能够启动一个新窗口,但是,如果我在其中调用pygame.quit()
(或sys.exit()
或pygame.display.quit()
) pygame程序,它也将关闭Tkinter窗口,我想保持打开状态。
我试图将pygame程序嵌入到Toplevel
窗口中,但是在我停止pygame主循环并在destroy()
窗口中调用Toplevel
之后,它关闭了,但是主Tk窗口冻结,并且不会响应任何用户输入,但是在调用destroy()
之后,代码将继续执行。
主循环
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()
设置
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()
链接到用于复制的完整代码的粘贴框:
图片供参考: