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

PySimpleGUI函数式创建多窗口时输入验证报错求助

解决PySimpleGUI双窗口函数式创建时的元素更新错误

问题场景

基于PySimpleGUI开发双窗口应用,采用函数式方法创建窗口并实现输入验证时,触发如下错误:

You cannot Update element with key = - until the window.read() is called or finalized

仅当不通过函数声明窗口时功能正常。

错误原因

  1. 跨窗口访问不存在的元素:每次主循环都执行for key in validate_inputs: window[key].bind(...),但validate_inputs包含两个窗口的输入key,当当前window是window1时,不存在IN2对应的元素;当是window2时,不存在IN1对应的元素,导致尝试访问不存在的key触发错误。
  2. 重复绑定事件:每次循环都执行绑定操作,会导致同一事件被多次绑定,引发异常。
  3. key格式不匹配:validate_inputs定义的是('IN1', 'IN2'),但窗口中输入框的key是'-IN1-'、'-IN2-',导致验证逻辑无法正确匹配事件。

解决方案

  1. 在窗口创建函数内完成事件绑定:每个窗口只绑定自身存在的输入框事件,避免跨窗口访问无效元素。
  2. 统一key格式:将validate_inputs和窗口内的key统一为带短横线的格式(如'-IN1-'),确保事件匹配正确。
  3. 优化主循环逻辑:只处理当前窗口对应的事件和元素,避免无效操作。

修改后的完整代码

import PySimpleGUI as sg
import re

def select(element):
    element.Widget.select_range(0, 'end')
    element.Widget.icursor('end')

def validate(text):
    result = re.match(regex, text)
    return False if result is None or result.group() != text else True

regex = "^[+-]?([0-5](\.(\d{0,2}))?)?$"
old = {'-IN1-':'0.00', '-IN2-':'0.00'}
validate_inputs = ('-IN1-', '-IN2-')

def make_window1():
    layout = [
        [sg.Text('Window 1')],
        [sg.Input(enable_events=True, k='-IN1-', default_text='0.00')],
        [sg.Text(size=(20,1), k='-OUTPUT-')],
        [sg.Button('Launch 2'), sg.Button('Exit')]
    ]
    window = sg.Window('Window 1', layout, finalize=True)
    # 仅绑定当前窗口存在的元素事件
    window['-IN1-'].bind('<FocusIn>', ' IN')
    window['-IN1-'].bind('<FocusOut>', ' OUT')
    return window

def make_window2():
    layout = [
        [sg.Text('Window 2')],
        [sg.Input(enable_events=True, k='-IN2-', default_text='0.00')],
        [sg.Button('Exit')]
    ]
    window = sg.Window('Window 2', layout, finalize=True)
    # 仅绑定当前窗口存在的元素事件
    window['-IN2-'].bind('<FocusIn>', ' IN')
    window['-IN2-'].bind('<FocusOut>', ' OUT')
    return window

def main():
    window1, window2 = make_window1(), None
    while True:
        window, event, values = sg.read_all_windows()
        
        # 处理窗口关闭事件
        if window == window1 and event in (sg.WIN_CLOSED, 'Exit'):
            break
        if window == window2 and event in (sg.WIN_CLOSED, 'Exit'):
            window2.close()
            window2 = None
            continue
        
        # 处理输入验证事件
        if event in validate_inputs:
            element, text = window[event], values[event]
            if validate(text):
                try:
                    v = float(text)
                    if v > 5:
                        element.update(old[event])
                        continue
                except ValueError:
                    pass
                old[event] = text
            else:
                element.update(old[event])
        # 处理焦点进入事件
        elif event.endswith(' IN'):
            key = event.split()[0]
            if key in window.AllKeysDict:  # 确保元素存在
                select(window[key])
        # 处理焦点离开事件
        elif event.endswith(' OUT'):
            key = event.split()[0]
            if key in window.AllKeysDict:  # 确保元素存在
                text = values[key]
                try:
                    v = float(text)
                    window[key].update(f'{v:.2f}')
                    old[key] = f'{v:.2f}'
                except ValueError:
                    window[key].update('0.00')
                    old[key] = '0.00'
        # 启动第二个窗口
        elif event == 'Launch 2' and not window2:
            window2 = make_window2()

    window1.close()
    if window2 is not None:
        window2.close()

if __name__ == '__main__':
    main()

关键修改点说明

  • 将事件绑定从主循环移到每个窗口的创建函数中,确保只绑定当前窗口存在的元素。
  • 统一了old字典、validate_inputs和窗口输入框的key格式,避免匹配错误。
  • 在处理焦点事件时,增加了key in window.AllKeysDict的判断,确保只操作当前窗口存在的元素。
  • 给输入框添加了default_text,初始化值与old字典保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:09:26