问题描述
我有一个 ttk.ComboBox
,我的用户可以从选项的下拉列表中进行选择,或者手动输入一些内容。我将它绑定到 Return
,这样如果我的用户在创建一个更改它会更新,但是如果我的用户单击该框并不小心输入了其他内容,则会导致错误。需要明确的是,我已经有一个绑定到新选择的事件,以及按下回车键。
我在问是否可以检查当焦点离开框时框值是否已更改,如果是,则调用函数?当我尝试 FocusOut
绑定时,每次我单击其中一个下拉列表时,它都会调用我的函数,并且不允许我从下拉列表中选择任何内容,因此无法正常工作。
selection.bind('<Return>',lambda event,entry=selection,row=row: update(
updated_entry=entry.get(),row=row,entry=entry))
selection.bind('<<ComboBoxSelected>>',entry=entry))
编辑:这是一个示例代码。这样写的方式,如果用户从下拉列表中选择一个项目,它会更新标签。如果用户输入内容并按下 Return 键,它会更新标签。但是如果用户输入内容并点击另一个下拉菜单,它不会更新标签。
import tkinter as tk
from tkinter import ttk
def update(updated_entry,row,entry):
label = tk.Text(root,height=1,width=10)
label.insert(tk.END,updated_entry)
label.grid(row=row,column=2)
return 'break'
def gui(root):
root.geometry('300x150')
root.config(background='sNow3')
for row in range(2):
options = ['test','test1','test2']
selection = tk.ttk.ComboBox(root,value=options)
selection.bind('<Return>',row=row: update(
updated_entry=entry.get(),entry=entry))
selection.bind('<<ComboBoxSelected>>',entry=entry))
selection.grid(row=row,column=1)
label = tk.Text(root,width=10)
label.grid(row=row,column=2)
if __name__ == '__main__':
root = tk.Tk()
gui(root)
tk.mainloop()
解决方法
ttk.Combobox
es 是 Entry
小部件的子类,这意味着您可以将 validation 添加到它们的基类中。即通过使用 validate=
和 validatecommand=
选项 Entry
的支持。
这样做的原因是因为“验证”将允许在失去焦点时检查关联的 Combobox
的内容 - 即你的既定目标。这应该与您已有的绑定事件处理结合使用。以下代码与您的最小可重现示例类似,说明了如何处理类似的事情。
注意:这种方法还允许对用户输入的值进行一些真正的验证,以防止以后出现问题(如果它们无效)。
import tkinter as tk
from tkinter import ttk
def update(updated_entry,entry):
''' Combobox change Callback. '''
entry.delete('1.0',tk.END)
entry.insert(tk.END,updated_entry)
def gui(root):
root.geometry('300x150')
root.config(background='snow3')
for row in range(2):
text = tk.Text(root,height=1,width=10) # Widget to be updated.
text.grid(row=row,column=2)
def check_okay(new_value,text=text):
update(new_value,text)
return True # Note: accepts anything.
combobox = ttk.Combobox(root,value=('test','test1','test2'),validate='focusout',validatecommand=(root.register(check_okay),'%P'))
combobox.grid(row=row,column=1)
combobox.bind('<Return>',lambda event,entry=combobox,text=text:
update(entry.get(),entry=text))
combobox.bind('<<ComboboxSelected>>',text=text:
update(entry.get(),entry=text))
if __name__ == '__main__':
root = tk.Tk()
gui(root)
tk.mainloop()