如何在外部函数中调用CustomTkinter输入对话框并解决冻结问题
CustomTkinter弹窗集成冻结问题解决方案
问题根源
你的代码冻结是因为CustomTkinter(基于Tkinter)属于事件驱动模型,而原项目是同步执行逻辑。直接在同步代码流中实例化弹窗并等待输入,会阻塞Tkinter的事件循环,导致界面无响应。
解决思路
改用「局部事件循环等待+回调传递结果」的模式:在弹窗初始化后启动局部事件循环,暂停主线程逻辑直到用户完成操作;通过回调函数接收用户选择,继续后续处理。
代码重构示例
1. 修改InputGetter弹窗类
import customtkinter as ctk class InputGetter(ctk.CTkToplevel): def __init__(self, confirm_callback, *args, **kwargs): super().__init__(*args, **kwargs) self.confirm_callback = confirm_callback self.selected_value = None # 弹窗基础配置 self.title("场景选择") self.geometry("300x200") self.resizable(False, False) # 构建界面元素 ctk.CTkLabel(self, text="请手动选择场景:").pack(pady=20) self.option_menu = ctk.CTkOptionMenu(self, values=["场景1", "场景2", "场景3"]) self.option_menu.pack(pady=10) ctk.CTkButton(self, text="确认", command=self._on_confirm).pack(pady=10) # 启动局部事件循环,阻塞到窗口关闭 self.wait_window(self) def _on_confirm(self): self.selected_value = self.option_menu.get() self.confirm_callback(self.selected_value) self.destroy()
2. 调整ScenarioIdentifier的调用逻辑
class ScenarioIdentifier: def execute(self): # 原有自动识别逻辑 auto_scenario = self._auto_detect_scenario() if not auto_scenario: # 弹窗请求用户输入,主线程暂停到弹窗关闭 def handle_selection(selection): self._process_selected_scenario(selection) InputGetter(handle_selection) def _auto_detect_scenario(self): # 模拟识别失败的情况 return None def _process_selected_scenario(self, selection): # 处理用户选择的场景 print(f"用户选择场景:{selection}") # 后续业务逻辑...
3. 主函数优化
确保主事件循环正常启动,若不需要主窗口可隐藏:
def main(): ctk.set_appearance_mode("system") ctk.set_default_color_theme("blue") # 初始化主应用窗口(若无需显示则隐藏) main_app = ctk.CTk() main_app.withdraw() # 启动业务流程 graph_builder = GraphBuilder() graph_builder.process() # 启动主事件循环 main_app.mainloop()
关键要点
wait_window(self):启动局部事件循环,让主线程暂停等待弹窗关闭,既保证同步逻辑的暂停需求,又不阻塞全局事件循环。- 回调函数:用于传递用户选择结果,后续业务逻辑在回调中执行,符合GUI事件驱动的设计模式。
- 主窗口处理:若仅用弹窗交互,可通过
withdraw()隐藏主窗口,避免多余界面干扰。
内容的提问来源于stack exchange,提问作者Gustavo Trivelatto
相关产品推荐
相关产品推荐

