Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default to and select first item in Tkinter listbox

I want to automatically select the first item in the listbox. By selecting the first item, I don't mean simply defaulting to the first item or setting focus on it. I've already achieved that by doing self.listbox.select_set(0). I want the default item also selected. In other words, when I run my code below, I want print(value) to print the value of the default selection. If Asia is chosen from the optionmenu, Japan should automatically print to the console. If Africa, Nigeria should print and Germany for Europe.

Any suggestion on how I can achieve this? Thanks.

from tkinter import *
from tkinter import ttk
import tkinter.messagebox

class App:
    def __init__(self):
        self.master = Tk()
        self.di = {'Asia': ['Japan', 'China', 'Malaysia', 'India', 'Korea',
                            'Vietnam', 'Laos', 'Thailand', 'Singapore',
                            'Indonesia', 'Taiwan'],
                     'Europe': ['Germany', 'France', 'Switzerland'],
                     'Africa': ['Nigeria', 'Kenya', 'Ethiopia', 'Ghana',
                                'Congo', 'Senegal', 'Guinea', 'Mali', 'Cameroun',
                                'Benin', 'Tanzania', 'South Africa', 'Zimbabwe']}
        self.variable_a = StringVar()
        self.frame_optionmenu = ttk.Frame(self.master)
        self.frame_optionmenu.pack()
        options = sorted(self.di.keys())
        self.optionmenu = ttk.OptionMenu(self.frame_optionmenu, self.variable_a, options[0], *options)

        self.variable_a.set('Asia')
        self.optionmenu.pack()
        self.btn = ttk.Button(self.master, text="Submit", width=8, command=self.submit)
        self.btn.pack()

        self.frame_listbox = ttk.Frame(self.master)

        self.frame_listbox.pack(side=RIGHT, fill=Y)
        self.scrollbar = Scrollbar(self.frame_listbox )
        self.scrollbar.pack(side=RIGHT, fill=Y)
        self.listbox = Listbox(self.frame_listbox, selectmode=SINGLE, yscrollcommand=self.scrollbar.set)
        self.variable_a.trace('w', self.updateoptions)

        self.scrollbar.config(command=self.listbox.yview)
        self.listbox.pack()

        #Populate listbox
        for each in self.di[self.variable_a.get()]:
            self.listbox.insert(END, each)
            self.listbox.select_set(0) #This only sets focus on the first item.
        self.listbox.bind("<<ListboxSelect>>", self.OnSelect)

        self.master.mainloop()

    def updateoptions(self, *args):
        #countries = self.di[self.variable_a.get()]
        self.listbox.delete(0, 'end')
        for each in self.di[self.variable_a.get()]:
            self.listbox.insert(END, each)
            self.listbox.select_set(0) #This only sets focus on the first item.
        self.listbox.pack()

    def submit(self, *args):
        var = self.variable_a.get()
        if messagebox.askokcancel("Selection", "Confirm selection: " + var):
            print(var)

    def OnSelect(self, event):
        widget = event.widget
        value = widget.get(widget.curselection()[0])
        print(value)

App()

Running Python 3.4.1

like image 793
sedeh Avatar asked Aug 20 '14 23:08

sedeh


1 Answers

The simplest solution is to generate the <<ListboxSelect>> event at the same time that you change the selection:

def updateoptions(self, *args):
    ...
    self.listbox.select_set(0) #This only sets focus on the first item.
    self.listbox.event_generate("<<ListboxSelect>>")
    ...
like image 174
Bryan Oakley Avatar answered Oct 06 '22 13:10

Bryan Oakley