如何使用 tkinter 将回调绑定到列表框?

How do I bind callbacks to a listbox using tkinter?

我正在玩 tkinter,并且在使用列表框时遇到了一些困难。我想将任意函数绑定到选择事件。据我了解 - 它应该是这样的。

import Tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        lb = tk.Listbox(self)
        lb.insert("end", "one")
        lb.insert("end", "two")
        lb.insert("end", "three")
        lb.bind("<Double-Button-1>", self.OnDouble)
        lb.pack(side="top", fill="both", expand=True)

    def OnDouble(self, event):
        widget = event.widget
        selection=widget.curselection()
        value = widget.get(selection[0])
        print "selection:", selection, ": '%s'" % value

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

我的理解是,当双击列表框中的元素时,会创建一个虚拟事件,该事件可以绑定到回调函数 - 在本例中定义了 OnDouble 函数。 我对其中的复杂性感到有点困惑,有人能准确解释这个 OnDouble 函数中发生了什么吗?

我试图在从列表框中选择一个元素时触发一个事件 - 我正在使用 pygubu 来设计 GUI,但我知道语法仍然遵循 tkinter 约定:

class TestApp:
def __init__(self):
    self.builder = builder = pygubu.Builder()
    builder.add_resource_path(PROJECT_PATH)
    builder.add_from_file(PROJECT_UI)
    self.mainwindow = builder.get_object('toplevel_1')
    builder.connect_callbacks(self)
    self.box = builder.get_object('listbox_1')
    self.list = [1,2,3,4]
    self.box.insert(tk.END, self.list[0])
    self.box.insert(tk.END, self.list[1])
    self.box.insert(tk.END, self.list[2])
    self.box.insert(tk.END, self.list[3])
    self.console = builder.get_object('text_1')


def print_console(self, msg):
    self.console.configure(state="normal")
    self.console.insert(tk.END, msg+"\n")
    self.console.configure(state="disabled")
    self.console.update_idletasks()
    


def run(self):
    self.mainwindow.mainloop()

if __name__ == '__main__':
    app = TestApp()
    app.run()

基本上,当在列表框中双击所述数字时,我希望控制台打印(使用定义的命令)类似 f'You have selected number {number}' 的内容。我怎样才能做到这一点?我会很感激它背后的工作原理,这样我就可以将它应用到更复杂的练习中,并理解解决方案而不仅仅是 copy/paste 它。

列表框中的项目可以通过单击选择,但也可以通过键盘选择。因此,绑定到特定的物理事件(例如 <Double-1>)并不是在选择更改时收到通知的最佳方式。

在列表框的特定情况下,绑定到 <<ListboxSelect>> 是最好的绑定事件,因为无论选择如何设置,该事件都将在设置选择后生成。

例如:

lb.bind("<<ListboxSelect>>", self.onSelect)

当通过绑定调用函数时,系统会自动向其传递一个参数,其中包含有关触发函数调用的事件的详细信息。其中一个参数是 widget,它是对接收调用的小部件的引用。

在您的特定情况下,您可以忽略它并在绑定函数中使用 self.listbox,但使用 event.widget 是养成的好习惯。这就是为什么您复制的代码以 widget = event.widget

开头的原因

下一步是获取选定的一个或多个项目。在您的情况下,一次只允许一个选择。但是,curselection 方法总是 returns 一个列表。 selection[0] 将引用所选项目,如果有选择。

注意:<<ListboxSelect>> 事件在设置选择或未设置选择时都会触发,因此如果通过某种方式取消选择项目,您问题中的代码可能会失败。

最后,一旦您有了所选项目的索引(例如:selection[0]),您就可以使用该数字索引来获取所选项目的文本。这就是行 value = widget.get(selection[0]) 所做的。