使用 PySimpleGUI,如何在光标不自动移动到下一个元素的情况下 运行 一个 'FocusOut' 事件?
Using PySimpleGUI, how do I run a 'FocusOut' event without the cursor moving to the next element automatically?
我附上了一个使用 PySimpleGUI 的大型程序的摘录。我正在使用 FocusOut 来测试输入框中是否输入了任何内容(或者是否选择了日期)。每个测试本身都能很好地提供弹出消息,然后将焦点返回到空元素。添加第二个和第三个 etc 元素时会出现问题。然后,如果您未能在第一个元素中输入内容,您会在焦点返回到第一个之前获得 2 或 3 个连续的弹出窗口。显然,缺少某些东西会使每个元素在触发下一个事件之前完成其事件。任何帮助将不胜感激。
enter code here
from datetime import date
import PySimpleGUI as sg
TodayDt=date.today()
print("Today's date is " + str(TodayDt))
layout=[
[sg.T("Today's date is:"),sg.InputText(TodayDt, size=(10, 10), key='_TODAYCAL_')],
[sg.T("Select new transaction date:"),sg.CalendarButton('Calendar', target='-IN4-', key='_DATE_',format='%Y-%m-%d'),sg.In(key='-IN4-', size=(10,1))],
[sg.T("Fuel quantity (in litres):"),sg.In(key="_FUELQUANT_",size=(10,1),enable_events=True),sg.T("Fuel amount N$:"),sg.In(key="_FUELAMNT_", size=(10,1),enable_events=True)],
[sg.T("Oil quantity (in millilitres:"),sg.In(key="_OILQUANT_",size=(10,1)),sg.T("Oil amount N$:"),sg.In(key="_OILAMNT_",size=(10,1))],
]
window = sg.Window('My Vehicle Logbook', layout, finalize=True)
iFuelQuant=window['_FUELQUANT_']
iFuelQuant.bind('<FocusOut>','FOCUS OUT')
fFuelAmnt=window['_FUELAMNT_']
fFuelAmnt.bind('<FocusOut>','FOCUS OUT')
dNewDt=window['-IN4-']
dNewDt.bind('<FocusOut>','FOCUS OUT')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
if event=='-IN4-FOCUS OUT':
text=values['-IN4-']
print(text)
if text=='':
sg.popup("Warning","You haven't selected a date")
window.find_element('_DATE_')
window.find_element('_DATE_').SetFocus()
continue
if event=='_FUELQUANT_' and values['_FUELQUANT_']:
try:
fFuelQuant=float(values['_FUELQUANT_'])
fFuelQuant="{: .2f}".format(float(fFuelQuant))#(in_as_float)
print(fFuelQuant)
except:
if len(values['_FUELQUANT_'])== 1 and values['_FUELQUANT_'][0]=='-':
sg.popup()
continue
window['_FUELQUANT_'].update(values['_FUELQUANT_'][:-1])
if event=='_FUELQUANT_FOCUS OUT':
try:
fFuelQ = (values['_FUELQUANT_'])
fFuelQ = "{: .2f}".format(float(fFuelQ))
window.find_element('_FUELQUANT_').update(fFuelQ)
print(fFuelQ)
continue
except:
if len(fFuelQ) == 0:
sg.popup("Warning!!!","You have not entered a fuel quantity")
#window.find_element('_FUELQUANT_').refresh('')
window.find_element('_FUELQUANT_').SetFocus()
#continue
if event=='_FUELAMNT_' and values['_FUELAMNT_']:
try:
fFuelAmnt=float(values['_FUELAMNT_'])
fFuelAmnt="{: .2f}".format(float(fFuelAmnt))#(in_as_float)
print(fFuelQuant)
except:
if len(values['_FUELAMNT_'])== 1 and values['_FUELAMNT_'][0]=='-':
sg.popup()
continue
window['_FUELAMNT_'].update(values['_FUELAMNT_'][:-1])
if event=='_FUELAMNT_FOCUS OUT':
try:
fFuelAmnt = (values['_FUELAMNT_'])
fFuelAmnt = "{: .2f}".format(float(fFuelAmnt))
window.find_element('_FUELAMNT_').update(fFuelAmnt)
print(fFuelAmnt)
continue
except:
if len(fFuelAmnt) == 0:
sg.popup("Warning!!!","You have not entered a fuel amount")
#window.find_element('_FUELQUANT_').refresh('')
window.find_element('_FUELAMNT_').SetFocus()
#continue
window.close()
FocusIn, FocusOut
The FocusIn and FocusOut events are generated whenever the keyboard focus changes. A FocusOut event is sent to the old focus window, and a FocusIn event is sent to the new one.
In addition, if the old and new focus windows do not share a common parent, “virtual crossing” focus events are sent to the intermediate windows in the hierarchy. Thus a FocusIn event indicates that the target window or one of its descendants has acquired the focus, and a FocusOut event indicates that the focus has been changed to a window outside the target window's hierarchy.
The keyboard focus may be changed explicitly by a call to focus, or implicitly by the window manager.
所以当你调用sg.popup
或sg.set_focus
时会产生focus out事件,然后事件会一次又一次地产生,这就是弹出window一次又一次显示的原因.
这是演示它的短代码,五个输入,但只有第二个和第三个检查它为空条目。
import PySimpleGUI as sg
def popup(*args, elem=None):
for element in elements:
element.unbind('<FocusOut>')
window.refresh() # Make unbind effect
layout = [
[sg.Text('\n'.join(args))],
[sg.Button('OK')],
]
sg.Window('Popup', layout).read(close=True)
if elem:
elem.set_focus()
window.refresh() # Make set_focus effect
for element in elements:
element.bind('<FocusOut>','+FOCUS OUT')
layout=[[sg.Input(key=f'-IN{i}-')] for i in range(5)]
window = sg.Window('My Vehicle Logbook', layout, finalize=True)
keys = ('-IN1-', '-IN2-')
elements = [window[key] for key in keys]
for element in elements:
element.bind('<FocusOut>','+FOCUS OUT')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
elif event.endswith("+FOCUS OUT"):
print(event)
key = event.split('+')[0]
if values[key] == '':
popup("Warning", f"Blank entry in {key} is not accept !", elem=window[key])
window.close()
我附上了一个使用 PySimpleGUI 的大型程序的摘录。我正在使用 FocusOut 来测试输入框中是否输入了任何内容(或者是否选择了日期)。每个测试本身都能很好地提供弹出消息,然后将焦点返回到空元素。添加第二个和第三个 etc 元素时会出现问题。然后,如果您未能在第一个元素中输入内容,您会在焦点返回到第一个之前获得 2 或 3 个连续的弹出窗口。显然,缺少某些东西会使每个元素在触发下一个事件之前完成其事件。任何帮助将不胜感激。
enter code here
from datetime import date
import PySimpleGUI as sg
TodayDt=date.today()
print("Today's date is " + str(TodayDt))
layout=[
[sg.T("Today's date is:"),sg.InputText(TodayDt, size=(10, 10), key='_TODAYCAL_')],
[sg.T("Select new transaction date:"),sg.CalendarButton('Calendar', target='-IN4-', key='_DATE_',format='%Y-%m-%d'),sg.In(key='-IN4-', size=(10,1))],
[sg.T("Fuel quantity (in litres):"),sg.In(key="_FUELQUANT_",size=(10,1),enable_events=True),sg.T("Fuel amount N$:"),sg.In(key="_FUELAMNT_", size=(10,1),enable_events=True)],
[sg.T("Oil quantity (in millilitres:"),sg.In(key="_OILQUANT_",size=(10,1)),sg.T("Oil amount N$:"),sg.In(key="_OILAMNT_",size=(10,1))],
]
window = sg.Window('My Vehicle Logbook', layout, finalize=True)
iFuelQuant=window['_FUELQUANT_']
iFuelQuant.bind('<FocusOut>','FOCUS OUT')
fFuelAmnt=window['_FUELAMNT_']
fFuelAmnt.bind('<FocusOut>','FOCUS OUT')
dNewDt=window['-IN4-']
dNewDt.bind('<FocusOut>','FOCUS OUT')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
if event=='-IN4-FOCUS OUT':
text=values['-IN4-']
print(text)
if text=='':
sg.popup("Warning","You haven't selected a date")
window.find_element('_DATE_')
window.find_element('_DATE_').SetFocus()
continue
if event=='_FUELQUANT_' and values['_FUELQUANT_']:
try:
fFuelQuant=float(values['_FUELQUANT_'])
fFuelQuant="{: .2f}".format(float(fFuelQuant))#(in_as_float)
print(fFuelQuant)
except:
if len(values['_FUELQUANT_'])== 1 and values['_FUELQUANT_'][0]=='-':
sg.popup()
continue
window['_FUELQUANT_'].update(values['_FUELQUANT_'][:-1])
if event=='_FUELQUANT_FOCUS OUT':
try:
fFuelQ = (values['_FUELQUANT_'])
fFuelQ = "{: .2f}".format(float(fFuelQ))
window.find_element('_FUELQUANT_').update(fFuelQ)
print(fFuelQ)
continue
except:
if len(fFuelQ) == 0:
sg.popup("Warning!!!","You have not entered a fuel quantity")
#window.find_element('_FUELQUANT_').refresh('')
window.find_element('_FUELQUANT_').SetFocus()
#continue
if event=='_FUELAMNT_' and values['_FUELAMNT_']:
try:
fFuelAmnt=float(values['_FUELAMNT_'])
fFuelAmnt="{: .2f}".format(float(fFuelAmnt))#(in_as_float)
print(fFuelQuant)
except:
if len(values['_FUELAMNT_'])== 1 and values['_FUELAMNT_'][0]=='-':
sg.popup()
continue
window['_FUELAMNT_'].update(values['_FUELAMNT_'][:-1])
if event=='_FUELAMNT_FOCUS OUT':
try:
fFuelAmnt = (values['_FUELAMNT_'])
fFuelAmnt = "{: .2f}".format(float(fFuelAmnt))
window.find_element('_FUELAMNT_').update(fFuelAmnt)
print(fFuelAmnt)
continue
except:
if len(fFuelAmnt) == 0:
sg.popup("Warning!!!","You have not entered a fuel amount")
#window.find_element('_FUELQUANT_').refresh('')
window.find_element('_FUELAMNT_').SetFocus()
#continue
window.close()
FocusIn, FocusOut
The FocusIn and FocusOut events are generated whenever the keyboard focus changes. A FocusOut event is sent to the old focus window, and a FocusIn event is sent to the new one. In addition, if the old and new focus windows do not share a common parent, “virtual crossing” focus events are sent to the intermediate windows in the hierarchy. Thus a FocusIn event indicates that the target window or one of its descendants has acquired the focus, and a FocusOut event indicates that the focus has been changed to a window outside the target window's hierarchy.
The keyboard focus may be changed explicitly by a call to focus, or implicitly by the window manager.
所以当你调用sg.popup
或sg.set_focus
时会产生focus out事件,然后事件会一次又一次地产生,这就是弹出window一次又一次显示的原因.
这是演示它的短代码,五个输入,但只有第二个和第三个检查它为空条目。
import PySimpleGUI as sg
def popup(*args, elem=None):
for element in elements:
element.unbind('<FocusOut>')
window.refresh() # Make unbind effect
layout = [
[sg.Text('\n'.join(args))],
[sg.Button('OK')],
]
sg.Window('Popup', layout).read(close=True)
if elem:
elem.set_focus()
window.refresh() # Make set_focus effect
for element in elements:
element.bind('<FocusOut>','+FOCUS OUT')
layout=[[sg.Input(key=f'-IN{i}-')] for i in range(5)]
window = sg.Window('My Vehicle Logbook', layout, finalize=True)
keys = ('-IN1-', '-IN2-')
elements = [window[key] for key in keys]
for element in elements:
element.bind('<FocusOut>','+FOCUS OUT')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
elif event.endswith("+FOCUS OUT"):
print(event)
key = event.split('+')[0]
if values[key] == '':
popup("Warning", f"Blank entry in {key} is not accept !", elem=window[key])
window.close()