pythontkintertabslistbox

tkinter listbox selection error when switching tabs


I have a tabbed interface with listboxes on each tab. When changing tabs, the first selection on the new tab errors out (index error) but any selection after that is recognized correctly. I've managed to replicate the error in this simplified example:

import tkinter as tk
from tkinter import ttk

class App(tk.Tk):
    """basic class to replicate tab-switching error"""

    def __init__(self):
        """exactly what it looks like"""
        super().__init__()
        self.items = {'Alphic': ["A","B","C",'c','d'], 'Numera':['1','2','3','4','5','6']}

        self.selection = tk.StringVar()
        self.main = tk.Frame()
        self.tabs = ttk.Notebook(self.main)
        
        self.make_tabs()

        self.main.pack()


    def make_tabs(self):
        """create all tabs in collected data"""

        def make_tab(f, data):
            'create single tab'
            frame = ttk.Frame(self.tabs)
            select  = tk.Listbox(frame,
                                 width = 20,
                                 height = 8)
            
            def update_selection(*_):
                try:
                    index = [i for i in select.curselection()][0]
                except IndexError:
                    index = "This Error Right Here"
                print(index)
            
            
            for n,k in enumerate(data):
                print("inserting", n)
                select.insert(n+1,k)
    
            select.pack()
            frame.pack()
            select.bind('<<ListboxSelect>>', update_selection)
            return frame


        for i, k in self.items.items():
            self.tabs.add(make_tab(i,k), text=i)
            
        self.tabs.pack()

            
if __name__ == "__main__":
    a = App()
    a.mainloop()

This issue is causing a dangerous bug in a larger program, as the error allows the selected index to 'bleed thru' from the previously selected tab. I've isolated that bug to this issue.

I've tried examining the Event that's passed to see if there's any clarification to be had, but no dice --or clarification-- was to be found.


Solution

  • By default, the selection of a listbox will be clear if there is selection in other widget. Clear of the selection will also trigger the the event <<ListboxSelect>> which causes the exception.

    To keep the selection of the previous listbox, you need to set exportselection=False when creating those listboxes:

    select = tk.Listbox(frame,
                        exportselection=False,
                        width = 20,
                        height = 8)