Abel Gutiérrez
Abel Gutiérrez

Reputation: 450

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

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.

Upvotes: 1

Views: 498

Answers (2)

acw1668
acw1668

Reputation: 46669

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.

Upvotes: 3

AKX
AKX

Reputation: 168863

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...

Upvotes: 1

Related Questions