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

PYSimpleGUI点击按钮时输入框未触发FOCUSOUT事件的解决方法

解决PySimpleGUI输入框点击按钮时未触发FocusOut事件的问题

原问题代码

import PySimpleGUI as sg
def dialog():
    layout = [[sg.Text("Value1:",size=(5,1)), sg.I(key="-VALUE1-",size=(10,1),focus=True)],
              [sg.Text("Value2:", size=(5, 1)), sg.I(key="-VALUE2-", size=(10, 1),focus=True)],
              [sg.Text("",size=(5,1)),sg.OK(key="-OK-"),sg.B("Show",key="-SHOW-"),sg.Cancel(key="-CANCEL-")]]
    window = sg.Window("Inputdialog", layout,modal=True,finalize=True)
    window.Element("-VALUE1-").SetFocus()
    window["-VALUE1-"].bind('<FocusOut>', 'FOCUS OUT')
    window["-VALUE2-"].bind('<FocusOut>', 'FOCUS OUT')
    while True:
        event, values = window.read()
        print(event)
        if event in (sg.WIN_CLOSED, "-CANCEL-"):
            break
        if event in ("-SHOW-"):
            print(values)
        if event in ("-OK-"):
            return values
    window.close()

result = dialog()

问题说明

输入框之间按Tab键切换时,会正常生成FocusOut事件;但光标处于输入框中直接点击按钮时,当前输入框的FocusOut事件不会触发,需要强制触发该事件。

解决方案

方法1:通过焦点转移触发事件

添加一个隐藏控件,点击按钮时让该控件获取焦点,迫使当前输入框失去焦点从而触发FocusOut。修改后的代码如下:

import PySimpleGUI as sg
def dialog():
    # 新增隐藏文本框用于接收焦点
    layout = [[sg.Text("Value1:",size=(5,1)), sg.I(key="-VALUE1-",size=(10,1),focus=True)],
              [sg.Text("Value2:", size=(5, 1)), sg.I(key="-VALUE2-", size=(10, 1))],
              [sg.Text("",size=(5,1)),sg.OK(key="-OK-"),sg.B("Show",key="-SHOW-"),sg.Cancel(key="-CANCEL-")],
              [sg.Text("", key="-HIDDEN-", visible=False)]]
    window = sg.Window("Inputdialog", layout,modal=True,finalize=True)
    window.Element("-VALUE1-").SetFocus()
    window["-VALUE1-"].bind('<FocusOut>', 'FOCUS OUT')
    window["-VALUE2-"].bind('<FocusOut>', 'FOCUS OUT')
    
    def trigger_focus_out():
        # 让隐藏控件获取焦点,触发当前输入框的FocusOut
        window["-HIDDEN-"].set_focus()
    
    while True:
        event, values = window.read()
        print(event)
        if event in (sg.WIN_CLOSED, "-CANCEL-"):
            trigger_focus_out()
            break
        if event in ("-SHOW-", "-OK-"):
            trigger_focus_out()
            if event == "-SHOW-":
                print(values)
            else:
                return values
    window.close()

result = dialog()

方法2:直接模拟触发FocusOut事件

利用Tkinter的事件生成方法,直接给当前获焦的输入框发送<<FocusOut>>事件,无需额外控件。修改后的代码如下:

import PySimpleGUI as sg
def dialog():
    layout = [[sg.Text("Value1:",size=(5,1)), sg.I(key="-VALUE1-",size=(10,1),focus=True)],
              [sg.Text("Value2:", size=(5, 1)), sg.I(key="-VALUE2-", size=(10, 1))],
              [sg.Text("",size=(5,1)),sg.OK(key="-OK-"),sg.B("Show",key="-SHOW-"),sg.Cancel(key="-CANCEL-")]]
    window = sg.Window("Inputdialog", layout,modal=True,finalize=True)
    window.Element("-VALUE1-").SetFocus()
    window["-VALUE1-"].bind('<FocusOut>', 'FOCUS OUT')
    window["-VALUE2-"].bind('<FocusOut>', 'FOCUS OUT')
    
    def trigger_focus_out():
        # 获取当前获焦的输入框
        focused_elem = window.find_element_with_focus()
        if focused_elem and focused_elem.Key in ("-VALUE1-", "-VALUE2-"):
            # 直接触发FocusOut事件
            focused_elem.Widget.event_generate('<<FocusOut>>')
    
    while True:
        event, values = window.read()
        print(event)
        if event in (sg.WIN_CLOSED, "-CANCEL-"):
            trigger_focus_out()
            break
        if event in ("-SHOW-", "-OK-"):
            trigger_focus_out()
            if event == "-SHOW-":
                print(values)
            else:
                return values
    window.close()

result = dialog()

方案说明

  • 方法1逻辑简单,兼容性强,通过焦点转移的原生行为触发事件;
  • 方法2更贴近原生事件触发逻辑,无需额外添加控件,代码更简洁。

内容的提问来源于stack exchange,提问作者Phil De Blanck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 01:55:19