You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySimpleGUI多窗口应用:窗口3、4点击Calculate后事件循环崩溃

多窗口PySimpleGUI程序修复:Function3窗口Calculate按钮触发崩溃问题

问题描述

我正在开发一个包含4个窗口的简易GUI程序,首页窗口可跳转到3个功能窗口,完成操作后能返回首页。目前首页和Function2窗口导航及功能正常,但点击Function3窗口的Calculate按钮后,事件循环崩溃,尽管该窗口逻辑与Function2完全一致。原代码如下:

import PySimpleGUI as sg


def make_function1_window():
    
    layout = [
        [sg.Text("Calculate Function 1")],
        [sg.Text("0.0000", justification="right", background_color="#2a2a2a", text_color="white", relief="sunken", key="_DISPLAY_")],
        [sg.Input("Enter input...", justification="left", key="_F1_INPUT_")],
        [sg.Button("Calculate"), sg.Button("Home")]
    ]

    return sg.Window("Function1", layout)

def make_function2_window():
    
    layout = [
        [sg.Text("Calculate Function 2")],
        [sg.Text("0.0000", justification="right", background_color="#2a2a2a", text_color="white", relief="sunken", key="_DISPLAY_")],
        [sg.Input("Enter input...", justification="left", key="_F1_INPUT_")],
        [sg.Button("Calculate"), sg.Button("Home")]
    ]

    return sg.Window("Function2", layout)

def make_function3_window():
    
    layout = [
        [sg.Text("Calculate Function 2")],
        [sg.Text("0.0000", justification="right", background_color="#2a2a2a", text_color="white", relief="sunken", key="_DISPLAY_")],
        [sg.Input("Enter input...", justification="left", key="_F1_INPUT_")],
        [sg.Button("Calculate"), sg.Button("Home")]
    ]

    return sg.Window("Function3", layout)


layout_home = [
    [sg.Text("Welcome to the program", font=("Arial", 12, "bold"))],
    [sg.Button("Function 1"), sg.Button("Function 2"), sg.Button("Function 3")],
    [sg.Button("Exit")]
]

home_window = sg.Window("Program Home", layout_home)
function1_active = function2_active = function3_active = False


while True:

    if not function1_active:
        event, values = home_window.read()
        if event is None or event == "Exit":
            break

    if not function1_active and event == "Function 1":
        function1_active = True
        home_window.hide()
        function1_window = make_function1_window()

    if not function1_active and event == "Function 2":
        function2_active = True
        home_window.hide()
        function2_window = make_function2_window()

    if not function1_active and event == "Function 3":
        function3_active = True
        home_window.hide()
        function3_window = make_function3_window()

    if function1_active:
        event, values = function1_window.read()
        if event == None:
            break
        elif event == "Home":
            function1_active = False
            function1_window.close()
            home_window.un_hide()
        elif event == "Calculate":
            function1_window["_DISPLAY_"].update(value="Doing stuff")
            function1_window.refresh()

    if function2_active:
        event, values = function2_window.read()
        if event == None:
            break
        elif event == "Home":
            function2_active = False
            function2_window.close()
            home_window.un_hide()
        elif event == "Calculate":
            function2_window["_DISPLAY_"].update(value="Doing stuff")
            function2_window.refresh()

    if function3_active:
        event, values = function3_window.read()
        if event == None:
            break
        elif event == "Home":
            function3_active = False
            function3_window.close()
            home_window.un_hide()
        elif event == "Calculate":         
            function3_window["_DISPLAY_"].update(value="Doing stuff")
            function3_window.refresh()
                  
     
home_window.close()

问题原因

原事件循环逻辑存在致命缺陷:并行判断所有窗口的激活状态,导致多个窗口的read()方法被同时调用,引发事件处理冲突、阻塞,最终导致循环崩溃。

解决方案

改用PySimpleGUI提供的sg.read_all_windows()统一处理多窗口事件,同时重构代码结构,消除重复逻辑,简化状态管理。修复后的代码如下:

import PySimpleGUI as sg


def make_function_window(window_num):
    # 统一创建功能窗口的函数,消除重复代码
    layout = [
        [sg.Text(f"Calculate Function {window_num}")],
        [sg.Text("0.0000", justification="right", background_color="#2a2a2a", text_color="white", relief="sunken", key="_DISPLAY_")],
        [sg.Input(f"Enter input for Function {window_num}...", justification="left", key=f"_F{window_num}_INPUT_")],
        [sg.Button("Calculate"), sg.Button("Home")]
    ]
    return sg.Window(f"Function{window_num}", layout)


layout_home = [
    [sg.Text("Welcome to the program", font=("Arial", 12, "bold"))],
    [sg.Button("Function 1"), sg.Button("Function 2"), sg.Button("Function 3")],
    [sg.Button("Exit")]
]

home_window = sg.Window("Program Home", layout_home)
# 用字典管理已打开的功能窗口,简化状态跟踪
function_windows = {}

while True:
    # 统一读取所有窗口的事件,避免多read()冲突
    window, event, values = sg.read_all_windows()
    
    # 处理全局关闭事件
    if event is None or event == "Exit":
        # 关闭所有功能窗口
        for win in function_windows.values():
            win.close()
        home_window.close()
        break
    
    # 首页窗口事件处理
    if window == home_window:
        if event.startswith("Function"):
            # 提取功能窗口编号
            num = event.split()[-1]
            home_window.hide()
            # 创建并存储功能窗口
            function_window = make_function_window(num)
            function_windows[num] = function_window
    
    # 功能窗口事件处理
    else:
        # 获取当前功能窗口编号
        window_num = window.Title.split()[-1]
        if event == "Home":
            # 关闭功能窗口并返回首页
            window.close()
            del function_windows[window_num]
            home_window.un_hide()
        elif event == "Calculate":
            # 更新显示内容,无需手动调用refresh()
            window["_DISPLAY_"].update(value="Doing stuff")

关键改动说明

  • 用make_function_window统一创建功能窗口,修复原Function3窗口文本错误,消除重复代码。
  • 使用sg.read_all_windows()统一处理所有窗口事件,彻底解决多read()调用导致的冲突问题。
  • 用字典function_windows管理已打开的功能窗口,简化状态跟踪逻辑。
  • 移除不必要的refresh()调用,PySimpleGUI的update()方法会自动触发界面刷新。

内容的提问来源于stack exchange,提问作者Callum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 04:30:43