Home > Enterprise >  python tkinter listbox binding: why this function is called two times?
python tkinter listbox binding: why this function is called two times?

Time:08-24

I have two tkinter.Listboxes. The idea is to show one of the Listboxes, and when an item is selected, the other Listbox is shown. To do that I use grid_forget. This is the code:

import tkinter as tk

root = tk.Tk()

listbox1 = tk.Listbox(root)
listbox1.grid(row=0, column=0)

listbox1.insert(tk.END, "Item 1.1")
listbox1.insert(tk.END, "Item 1.2")

def change_listbox(event):
    
    print(listbox1.curselection())
    listbox1.grid_forget()
    listbox2.grid(row=0, column=0)

listbox1.bind("<<ListboxSelect>>", change_listbox)

listbox2 = tk.Listbox(root)

listbox2.insert(tk.END, "Item 2.1")
listbox2.insert(tk.END, "Item 2.2")

root.mainloop()

When I select an item from listbox1, the listbox2 is show, but when I select an item of the listbox2, change_listbox is called again (only one time). You can check this by the print I added.

However, if I change grid_forget by destroy the issue is solved, but I don't want to destroy listbox1.

CodePudding user response:

It is because when item in listbox2 is selected, the selected item in listbox1 will be deselected due to exportselection option is set to True by default. So it will trigger the bound event <<ListboxSelect>> on listbox1. Just set exportselection=False (or 0) in both listboxes will fix it.

CodePudding user response:

Since the calls are

(0,)

(or (1,)) when initially selecting the item from the listbox, followed by

()

(i.e. "nothing selected") it looks like the second invocation occurs when the item gets unselected from list 1 (since you're selecting an item from list 2).

You can verify this by laying out both listboxes side by side (so remove the forget stuff):

listbox1.grid(row=0, column=0)
listbox2.grid(row=0, column=1)

When you select an item in the second listbox, the selection in the first listbox is unselected.

If you don't care about that unselection, well... don't:

def change_listbox(event):
    sel = listbox1.curselection()
    if not sel:  # Nothing selected, whatever
        return
    print("Selected:", sel)
    # show list 2 or something...
  • Related