获取列表框中的选定项目并调用另一个存储选定项目的函数

2022-01-16 00:00:00 python tkinter tk listbox

问题描述

我有一个画布,当它被点击时会调用 createCategoryMeny(x).

I have a canvas that calls createCategoryMeny(x) when it is clicked.

这个函数只是创建一个Toplevel()窗口,

This function just creates a Toplevel() window,

def createCategoryMenu(tableNumber):

    ##Not interesting below:
    categoryMenu = Toplevel()
    categoryMenu.title("Mesa numero: " + str(tableNumber))
    categoryMenu.geometry("400x400+100+100")

    categoryMenu.focus()
    categoryMenu.grab_set()

    Label(categoryMenu, text="Elegir categoria 
 Mesa numero: " + str(tableNumber)).pack()


    ## RELEVANT CODE BELOW:
    listbox = Listbox(categoryMenu, width=50, height=len(info.listaCategorias))
    listbox.pack(pady=20)

    for item in info.listaCategorias:
        listbox.insert(END, item)

    listbox.selection_set(first=0)

    ##My attempt to solve it
    callback = lambda event, tag= "ThisShouldBeTheSelected!!": do(event, tag)
    listbox.bind("<Double-Button-1>", callback)

然后是do函数:

def do(event, tag):
    print tag

这成功打印了`"ThisShouldBeTheSelected!!"``.

This successfully prints `"ThisShouldBeTheSelected!!"``.

这就是我完全陷入困境的地方.

And this is where I am utterly stuck.

我无法获得双击的元素(被选中的元素).

I cant get the double clicked element (the selected one).

我想将它作为 tag= 传递.

I want to pass it as tag=.

我试过了:

listbox.curselection()

总是打印 ('0',)

如果我删除 listbox.selection_set(first=0),我只会得到这个:()

If I remove listbox.selection_set(first=0), I only get this: ()

所以问题是:

  • 如何获取选中项(双击项)
  • (不是那么重要)像我这样将它传递给其他函数是否合理?

注意:

我发现这个:

8.5.为什么 .listbox curselection 或 selection 不返回当我将按钮绑定到我的列表框时正确的项目?

在按钮单击事件期间获取所选项目的最佳方式listbox就是使用如下代码:

The best way to get the selected item during a button click event on a listbox is to use the following code:

bind .listbox { set item [%W get [%W nearest %y]] }

bind .listbox { set item [%W get [%W nearest %y]] }

这样可以确保指针下的项目是要返回的作为项目..listbox curselection 可能失败的原因是因为在 Listbox 类绑定之前,不会设置 curselection 中的项目触发器,默认情况下在实例绑定之后.这是选择获取失败的相同原因,但它也会如果将 -exportselection 选项设置为 0,则会失败.

This ensures that the item under the pointer is what will be returned as item. The reason .listbox curselection can fail is because the items in curselection are not set until the Listbox class binding triggers, which is after the instance bindings by defaults. This is the same reason for which selection get can fail, but it will also fail if you set the -exportselection option to 0.

我不确定它是否有帮助,我不太明白它在说什么.

I'm not sure if it's helpful, I don't really understand what it is saying.


解决方案

首先,不要使用 lambda.它对一小部分问题很有用,而这不是其中之一.创建一个合适的函数,它们更容易编写和维护.

For one, don't use lambda. It's useful for a narrow range of problems and this isn't one of them. Create a proper function, they are much easier to write and maintain.

一旦你这样做了,你可以调用 curselection 来获取当前的选择.你说你试过了,但你的示例代码没有显示你尝试了什么,所以我只能假设你做错了.

Once you do that, you can call curselection to get the current selection. You say you tried that but your example code doesn't show what you tried, so I can only assume you did it wrong.

至于使用 nearest 的相当不寻常的建议......它的意思是,您在小部件上放置的绑定发生在同一事件的默认绑定之前.它是设置选择的默认绑定,因此当您绑定到 single 按钮单击时,您的绑定会在默认绑定更新选择之前触发.有很多方法可以解决这个问题,其中最好的方法是不单击一次绑定,而是绑定 <<ListboxSelect>>选择已更改.

As for the rather unusual advice to use nearest... all it's saying is that bindings you put on a widget happen before default bindings for that same event. It is the default bindings that set the selection, so when you bind to a single button click, your binding fires before the selection is updated by the default bindings. There are many ways around that, the best of which is to not bind on a single click, but instead bind on <<ListboxSelect>> which will fire after the selection has changed.

但是,您没有这个问题.由于您是通过双击绑定的,因此默认单击绑定将设置选择,并且 curselection 将返回正确的值.也就是说,除非您有自己的单击绑定来阻止默认绑定触发.

You don't have that problem, however. Since you are binding on a double-click, the selection will have been set by the default single-click binding and curselection will return the proper value. That is, unless you have your own single-click bindings that prevent the default binding from firing.

这是一个简单的示例,它打印出选择,以便您可以看到它是正确的.从命令行运行它,你会看到标准输出:

Here's a simple example that prints out the selection so you can see it is correct. Run it from the command line so you see stdout:

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()

相关文章