【问题标题】:Bind Tkinter Combobox to Entry change?将 Tkinter 组合框绑定到条目更改?
【发布时间】:2021-06-30 15:55:52
【问题描述】:

我有一个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>>', lambda event, entry=selection, row=row: update(
    updated_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()

【问题讨论】:

  • @martineau 我添加了一个最小的可重现示例。
  • 我不清楚你想要完成什么。您在gui() 中的for 循环中创建Labels,然后update() 函数创建一个Text 小部件,并放置在其中一个或另一个之上。
  • 标签没有任何意义,我只是写了这个。在我的真实代码中,我正在调用一个函数来更新完全不同的东西,但这是我最小的可重现示例。我想要的是我的更新函数被称为 IF 文本已在下拉列表之一中更改。例如,如果您运行上述代码并在第一个组合框中键入 Hello 并按 Enter,它将运行更新功能并添加文本。但是,如果您在组合框中键入 hello 然后单击另一个组合框,它不会运行更新功能。如果输入了文本,我需要运行更新功能。
  • 将相同的 lambda 绑定到 &lt;FocusOut&gt; 事件后可以正常工作。

标签: python tkinter ttk


【解决方案1】:

ttk.Comboboxes 是Entry 小部件的子类,这意味着您可以像添加到它们的基类一样向它们添加validation。即通过使用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()

【讨论】:

  • 这完全符合预期,我能够在我的代码中实现这个方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-23
相关资源
最近更新 更多