将 Tkinter Combobox 绑定到条目更改?

Bind Tkinter Combobox to Entry change?

我有一个 ttk.Combobox,我的用户可以从选项的下拉列表中 select,或者手动输入一些内容。我将它绑定到 Return,所以如果我用户在进行更改后按 return 将更新,但如果我的用户单击该框并不小心键入其他内容,则会导致错误。需要明确的是,我已经有一个绑定到新 selection 的事件,以及按下 return.

请问是否可以在焦点离开框时检查框值是否已更改,如果是,则调用函数?当我尝试 FocusOut 绑定时,每次我单击其中一个下拉菜单时,它都会调用我的函数,并且不让我 select 下拉菜单中的任何内容,所以这是行不通的。

selection.bind('<Return>', lambda event, entry=selection, row=row: update(
    updated_entry=entry.get(), row=row, entry=entry))
selection.bind('<<ComboboxSelected>>', lambda event, entry=selection, row=row: update(
    updated_entry=entry.get(), row=row, entry=entry))

编辑:这是一个示例代码。这样写的方式,如果用户 select 从下拉列表中选择一个项目,它会更新标签。如果用户输入内容并按下 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>', lambda event, entry=selection, row=row: update(
            updated_entry=entry.get(), row=row, entry=entry))
        selection.bind('<<ComboboxSelected>>', lambda event, entry=selection, row=row: update(
            updated_entry=entry.get(), row=row, entry=entry))
        selection.grid(row=row, column=1)

        label = tk.Text(root, height=1, width=10)
        label.grid(row=row, column=2)

if __name__ == '__main__':
    root = tk.Tk()
    gui(root)
    tk.mainloop()

ttk.Comboboxes 是 Entry widgets, which means that you can add validation 的子class 对他们来说就像你对他们的基础 class 一样。即通过使用 validate=validatecommand= 选项 Entrys 支持。

这样做的原因是因为“验证”将允许在失去焦点时检查关联的 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>>', lambda event, entry=combobox, text=text:
                                                update(entry.get(), entry=text))

if __name__ == '__main__':
    root = tk.Tk()
    gui(root)
    tk.mainloop()