点击FreeSimpleGUI的Close按钮弹出错误弹窗,寻求解决方法
解决FreeSimpleGUI窗口关闭按钮报错问题
问题描述
我用FreeSimpleGUI开发了一个待办事项列表界面,点击“Exit”按钮程序能正常关闭,但点击窗口自带的“Close”按钮时会弹出错误弹窗,请问该怎么解决?这是我第一次发帖,若格式有问题请见谅。
代码示例
import functions import FreeSimpleGUI as sg import time import os if not os.path.exists("todos.txt"): with open("todos.txt", "w") as file: pass sg.theme("Black") clock = sg.Text('', key='clock') label = sg.Text("Type in a to-do") input_box = sg.InputText(tooltip="Enter to-do", key="todo") add_button = sg.Button("Add") list_box = sg.Listbox(values=functions.get_todos(), key='todos', enable_events=True, size=[45, 10]) edit_button = sg.Button("Edit") complete_button = sg.Button("Complete") exit_button = sg.Button("Exit") window = sg.Window('My To-Do App', layout=[[clock], [label], [input_box, add_button], [list_box, edit_button, complete_button], [exit_button]], font=('Helvetica', 20)) while True: event, values = window.read(timeout=500) window["clock"].update(value=time.strftime("%b %d, %Y %H:%M:%S")) match event: case "Add": todos = functions.get_todos() new_todo = values['todo'] + "\n" todos.append(new_todo) functions.write_todos(todos) window['todos'].update(values=todos) case "Edit": try: todo_to_edit = values['todos'][0] new_todo = values['todo'] + "\n" todos = functions.get_todos() index = todos.index(todo_to_edit) todos[index] = new_todo functions.write_todos(todos) window['todos'].update(values=todos) except IndexError: sg.popup("Please select an item first", font=("Helvetica", 20)) case "Complete": try: todo_to_complete = values['todos'][0] todos = functions.get_todos() todos.remove(todo_to_complete) functions.write_todos(todos) window['todos'].update(values=todos) window['todo'].update(value='') except IndexError: sg.popup("Please select an item first", font=("Helvetica", 20)) case "Exit": break case 'todos': window['todo'].update(value=values['todos'][0]) case sg.WIN_CLOSED: break window.close()
问题原因
点击窗口Close按钮触发sg.WIN_CLOSED事件后,代码虽然执行了break退出循环,但在这之前已经执行了window["clock"].update(...)——此时窗口已经进入关闭流程,调用界面元素的update方法会触发报错。
修复方案
把窗口关闭和Exit按钮的判断移到界面更新操作之前,确保触发关闭事件时直接退出循环,跳过所有后续的界面更新逻辑:
修改后的主循环代码:
while True: event, values = window.read(timeout=500) # 优先处理关闭事件,直接退出循环 if event == sg.WIN_CLOSED or event == "Exit": break # 仅窗口正常运行时执行界面更新和事件处理 window["clock"].update(value=time.strftime("%b %d, %Y %H:%M:%S")) match event: case "Add": todos = functions.get_todos() new_todo = values['todo'] + "\n" todos.append(new_todo) functions.write_todos(todos) window['todos'].update(values=todos) case "Edit": try: todo_to_edit = values['todos'][0] new_todo = values['todo'] + "\n" todos = functions.get_todos() index = todos.index(todo_to_edit) todos[index] = new_todo functions.write_todos(todos) window['todos'].update(values=todos) except IndexError: sg.popup("请先选择一个项目", font=("Helvetica", 20)) case "Complete": try: todo_to_complete = values['todos'][0] todos = functions.get_todos() todos.remove(todo_to_complete) functions.write_todos(todos) window['todos'].update(values=todos) window['todo'].update(value='') except IndexError: sg.popup("请先选择一个项目", font=("Helvetica", 20)) case 'todos': window['todo'].update(value=values['todos'][0]) window.close()
核心修复点
- 提前判断
sg.WIN_CLOSED和Exit事件,触发后直接退出循环,避免执行后续的界面更新操作 - 所有界面元素的
update方法仅在窗口正常运行时调用,从根源上避免窗口关闭后操作界面的错误
内容的提问来源于stack exchange,提问作者Orengasi Bassey
相关产品推荐
相关产品推荐

