Python中如何实现内容与控制两个窗口异步同时运行?
解决PyGame与Tkinter窗口同时运行的阻塞问题
你遇到的问题根源是Tkinter的window.mainloop()是阻塞式调用,会暂停后续代码执行,直到Tk窗口关闭后才会进入PyGame的循环。要让两个窗口同时响应操作,有两种可行方案:
方案一:将PyGame逻辑整合到Tkinter事件循环
利用Tkinter的after()方法定时触发PyGame的更新与事件处理,把两个窗口的逻辑合并到同一个主循环中,避免互相阻塞。
完整代码示例:
import pygame, sys, tkinter pygame.init() # 初始化PyGame内容窗口 surface = pygame.display.set_mode((750, 500), pygame.RESIZABLE) pygame.display.set_caption("Zamkoriada") stroke = 20 letter_matrix = [['A' for _ in range(29)] for _ in range(10)] # 创建Tkinter控制窗口 window = tkinter.Tk() window.title("Login") window.geometry("200x120") label = tkinter.Label(window, text="username") inputUser = tkinter.Entry(window) labelPassword = tkinter.Label(window, text="Password") inputPassword = tkinter.Entry(window) button = tkinter.Button(window, text="Go") label.pack() inputUser.pack() labelPassword.pack() inputPassword.pack() def update_pygame(): # 处理PyGame事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() window.destroy() sys.exit() if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: pygame.quit() window.destroy() sys.exit() if event.type == pygame.VIDEORESIZE: global surface surface = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE) # 更新PyGame画面 surface.fill((0,0,255)) if surface.get_width() < surface.get_height()*(192/108): block_width = (surface.get_width()-125-(28*2))/29 block_height = block_width*3/2 # 插入你的内容绘制代码 pygame.display.update() # 每隔16ms调用一次(约60帧/秒) window.after(16, update_pygame) # 启动PyGame更新任务 update_pygame() # 启动Tkinter主循环 window.mainloop()
方案说明
update_pygame()函数包含了PyGame的事件处理、画面更新逻辑- 通过
window.after(16, update_pygame)让Tkinter每隔16ms自动调用一次该函数,模拟PyGame的帧率 - 两个窗口的事件都由Tkinter的主循环处理,不会互相阻塞
方案二:使用线程分离两个窗口的循环
把PyGame的循环放到独立线程中运行,Tkinter的主循环留在主线程,实现并行执行。注意:Tkinter的所有操作必须在主线程中进行,避免线程安全问题。
完整代码示例:
import pygame, sys, tkinter, threading pygame.init() # 初始化PyGame内容窗口 surface = pygame.display.set_mode((750, 500), pygame.RESIZABLE) pygame.display.set_caption("Zamkoriada") stroke = 20 letter_matrix = [['A' for _ in range(29)] for _ in range(10)] # 创建Tkinter控制窗口 window = tkinter.Tk() window.title("Login") window.geometry("200x120") label = tkinter.Label(window, text="username") inputUser = tkinter.Entry(window) labelPassword = tkinter.Label(window, text="Password") inputPassword = tkinter.Entry(window) button = tkinter.Button(window, text="Go") label.pack() inputUser.pack() labelPassword.pack() inputPassword.pack() def pygame_loop(): running = True while running: # 更新PyGame画面 surface.fill((0,0,255)) if surface.get_width() < surface.get_height()*(192/108): block_width = (surface.get_width()-125-(28*2))/29 block_height = block_width*3/2 # 插入你的内容绘制代码 pygame.display.update() # 处理PyGame事件 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False window.quit() # 通知Tkinter窗口关闭 if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: running = False window.quit() if event.type == pygame.VIDEORESIZE: global surface surface = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE) pygame.quit() sys.exit() # 启动PyGame线程(daemon=True表示线程随主线程退出) pygame_thread = threading.Thread(target=pygame_loop, daemon=True) pygame_thread.start() # 启动Tkinter主循环 window.mainloop()
方案说明
- PyGame的循环在独立线程中运行,不会阻塞Tkinter的主循环
- 当关闭任意一个窗口时,通过
window.quit()或终止循环的方式通知另一个窗口退出 - 线程设置为daemon,确保主线程退出时子线程也会自动结束
内容的提问来源于stack exchange,提问作者zamkorus
相关产品推荐
相关产品推荐

