Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get selected item in listbox and call another function storing the selected for it

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

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 \n 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)

Then the do function:

def do(event, tag):
    print tag

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

And this is where I am utterly stuck.

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

I want to pass it as tag=.

I have tried:

listbox.curselection()

Which always prints ('0',)

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

So the questions are:

  • How can I get the selected item (the double clicked one)
  • (Not so important) Is it reasonable to pass it to the other function like I do?

Note:

I found this:

8.5. Why doesn't .listbox curselection or selection get return the proper item when I make a button binding to my 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]] }

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.

like image 697
Trufa Avatar asked Sep 30 '11 22:09

Trufa


People also ask

How do you retrieve the selected item in a ListBox?

To retrieve a collection containing all selected items in a multiple-selection ListBox, use the SelectedItems property. If you want to obtain the index position of the currently selected item in the ListBox, use the SelectedIndex property.

Which function is used to fetch a value based on the number returned by a list box control?

The CHOOSE function returns a value or a reference from a list of options, based on an index number.

How do you check ListBox is selected or not?

To determine the items that are selected, you can use the Selected property of the list box. The Selected property of a list box is an array of values where each value is either True (if the item is selected) or False (if the item is not selected).

How do I select a ListBox item in Python?

We can use the select_set(list_item_index) method by specifying the index of the list items that need to be selected by default.


1 Answers

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.

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.

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.

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()
like image 104
Bryan Oakley Avatar answered Oct 15 '22 11:10

Bryan Oakley