Search code examples
python-3.xloopstkintercomboboxdropdown

Tk Python combobox in loop get the data selected


I want to show in a loop a dropdown list and capture the data selected. I have the below code, but even printing it is not working.. Could someone help me please?

So let's say that on the 1st screen I chose a, b, c in that order, then on the 2nd I chose d, c, a in that order; and on the last I chose a, d, c in that order, I would like my final list to be:

lb_sel = [['a', 'b', 'c'],['d', 'c', 'a'],['a', 'd', 'c']]

from tkinter import filedialog, messagebox, ttk, constants
from tkinter import *


def DropDown(argslist,index):
    var = StringVar()
    c= ttk.Combobox(root,width=40)
    c['values'] = argslist
    c.textvariable=var
    c.current(0)
    c.bind("<<ComboboxSelected>>",choice_sel)
    c.grid(row=index-1, column=1,padx=(15,25))
    c.index=index

nb_choice = 3
has_choice = True
lst = ['a', 'b', 'c', 'd']
lb_sel = [[] for i in range(nb_choice)]

lst.insert(0,'Select a choice')
for i in range(nb_choice):
    root = Tk()
    root.focus_force()
    root.title('Choices')
    labl1 = ttk.Label(text = 'Select the first choice of N.' + str(i+1))
    labl1.grid(row = 0, column = 0)
    labl2 = ttk.Label(text = 'Select the second choice of N.' + str(i+1))
    labl2.grid(row = 1, column = 0)
    labl3 = ttk.Label(text = 'Select the third choice of N.' + str(i+1))
    labl3.grid(row = 2, column = 0)
    def choice_sel():
        print(lb1.get())
    lb1 = DropDown(lst,1)
    lb2 = DropDown(lst,2)
    lb3 = DropDown(lst,3)
    
    exit_but = Button(root, text = 'OK', command = lambda: choice_sel, height = 3, width = 5)
    exit_but.grid(row = 2, column = 2)
    root.mainloop()

Solution

  • The following code makes the work:

    from tkinter import filedialog, messagebox, ttk, constants
    from tkinter import *
    
    def choice_sel(index, *args, **kwargs):
        lb_sel[index-1].append(args[0].widget.get())
    
    def DropDown(argslist,index):
        var = StringVar()
        c= ttk.Combobox(root,width=40)
        c['values'] = argslist
        c.textvariable=var
        c.current(0)
        c.bind("<<ComboboxSelected>>",lambda event, index=index: choice_sel(index, event))
        c.grid(row=index-1, column=1,padx=(15,25))
        c.index=index
    
    nb_choice = 3
    has_choice = True
    lst = ['a', 'b', 'c', 'd']
    lb_sel = [[] for i in range(nb_choice)]
    
    lst.insert(0,'Select a choice')
    for i in range(nb_choice):
        root = Tk()
        root.focus_force()
        root.title('Choices')
        labl1 = ttk.Label(text = 'Select the first choice of N.' + str(i+1))
        labl1.grid(row = 0, column = 0)
        labl2 = ttk.Label(text = 'Select the second choice of N.' + str(i+1))
        labl2.grid(row = 1, column = 0)
        labl3 = ttk.Label(text = 'Select the third choice of N.' + str(i+1))
        labl3.grid(row = 2, column = 0)
        DropDown(lst,1)
        DropDown(lst,2)
        DropDown(lst,3)
        
        exit_but = Button(root, text = 'OK', command = choice_sel, height = 3, width = 5)
        exit_but.grid(row = 2, column = 2)
        root.mainloop()
    

    Result after pressing 'a' and 'b' on the first dropdown and 'b' on the second one:

    lb_sel = [['a', 'b'], ['b'], []]
    

    The things I have changed to make it work have been:

    1. Set choice_sel outside the for loop and add *args and *kwargs arguments since it was used on two different places of the code, one of which was necessary to pass the event argument. This was actually causing an error during run-time.
    2. Pass the index argument to the function too to know which was the pressed dropdown.
    3. Get the value of the combobox with the method widget.get().
    4. Remove the return variable from function DropDown since it does not return any value.

    Please bear in mind that you should probably reset/save the variable lb_sel when you close the main window to go to the next iteration of the for-loop.

    Side note: It is preferable to use TopLevel instead of creating multiple instances of Tk.