Python 将Tkinter组合框绑定到条目更改?

Python 将Tkinter组合框绑定到条目更改?,python,tkinter,ttk,Python,Tkinter,Ttk,我有一个ttk.Combobox,我的用户可以从选项下拉列表中选择,或者手动键入一些内容。我将它绑定到Return,因此如果我的用户在进行更改后按下Return,它将更新,但如果我的用户在框中单击并意外键入其他内容,它将导致错误。要明确的是,我已经有了一个绑定到新选择的事件,并按下了return键 我想问的是,当焦点离开框时,是否可以检查框值是否已更改,如果是,则调用函数?当我尝试一个FocusOutbind时,每次我点击其中一个下拉列表,它就会调用我的函数,并且不允许我从下拉列表中选择任何内容

我有一个
ttk.Combobox
,我的用户可以从选项下拉列表中选择,或者手动键入一些内容。我将它绑定到
Return
,因此如果我的用户在进行更改后按下Return,它将更新,但如果我的用户在框中单击并意外键入其他内容,它将导致错误。要明确的是,我已经有了一个绑定到新选择的事件,并按下了return键

我想问的是,当焦点离开框时,是否可以检查框值是否已更改,如果是,则调用函数?当我尝试一个
FocusOut
bind时,每次我点击其中一个下拉列表,它就会调用我的函数,并且不允许我从下拉列表中选择任何内容,因此这不起作用

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.bind(“”,lambda事件,条目=选择,行=行:更新(
更新了(entry=entry.get(),row=row,entry=entry))
selection.bind(“”,lambda事件,条目=选择,行=行:更新(
更新了(entry=entry.get(),row=row,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>', 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()
将tkinter作为tk导入
从tkinter导入ttk
def更新(更新的_条目、行、条目):
label=tk.Text(根,高度=1,宽度=10)
标签.插入(tk.END,更新的\u条目)
label.grid(行=行,列=2)
返回“中断”
def gui(根目录):
root.geometry('300x150')
root.config(background='snow3')
对于范围(2)中的行:
选项=['test'、'test1'、'test2']
selection=tk.ttk.Combobox(根,值=选项)
selection.bind(“”,lambda事件,条目=选择,行=行:更新(
更新了(entry=entry.get(),row=row,entry=entry))
selection.bind(“”,lambda事件,条目=选择,行=行:更新(
更新了(entry=entry.get(),row=row,entry=entry))
selection.grid(行=行,列=1)
label=tk.Text(根,高度=1,宽度=10)
label.grid(行=行,列=2)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=tk.tk()
gui(根目录)
tk.mainloop()

ttk.Combobox
es是小部件的一个子类,这意味着您可以像添加基类一样添加到它们。即使用
validate=
validatecommand=
options
Entry
s支持

这样做的原因是,“验证”将允许在相关的
组合框
失去焦点时检查其内容,即您声明的目标。这与您已有的绑定事件处理结合起来应该可以很好地工作。下面的代码类似于您的最小可复制示例,说明了如何处理类似的事情

注意:这种方法还允许对用户输入的值进行一些真正的验证,以防止以后这些值无效时出现问题

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()
将tkinter作为tk导入
从tkinter导入ttk
def更新(更新的_条目,条目):
''组合框更改回调''
条目.删除('1.0',tk.END)
条目.插入(tk.END,更新的\u条目)
def gui(根目录):
root.geometry('300x150')
root.config(background='snow3')
对于范围(2)中的行:
text=tk.text(根,高度=1,宽度=10)#要更新的小部件。
text.grid(行=行,列=2)
def check_OK(新_值,text=text):
更新(新值,文本)
返回True#注意:接受任何内容。
combobox=ttk.combobox(根,值=('test','test1','test2'),
validate='focusout',
validatecommand=(root.register(检查是否正确),'%P'))
combobox.grid(行=行,列=1)
combobox.bind(“”,lambda事件,条目=combobox,文本=文本:
更新(entry.get(),entry=text))
combobox.bind(“”,lambda事件,条目=combobox,文本=文本:
更新(entry.get(),entry=text))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=tk.tk()
gui(根目录)
tk.mainloop()

@martineau我添加了一个最小的可重复性示例。我不清楚您想要实现什么。你在
gui()
循环中为
创建
Label
s,然后
update()
函数创建一个
Text
小部件,放在其中一个上面。这个标签实际上没有任何意义,我只是写了这个。在我的实际代码中,我调用一个函数来更新完全不同的内容,但这是我的最小可复制示例。我想要的是,如果其中一个下拉列表中的文本已更改,则调用我的更新函数。例如,如果运行上述代码并在第一个组合框中键入Hello并按enter键,它将运行update函数并添加文本。但是,如果在组合框中键入hello,然后单击另一个组合框,则不会运行更新功能。如果输入了文本,我需要运行update函数。将相同的lambda绑定到
事件后,它可以正常工作。这完全符合预期,并且我能够在代码中实现此方法。非常感谢。