On change of OptionMenu in a for loop

Viewed 34

I would like to create multiple OptionMenus, with different option seleted, the corresponding Labels and Entries are shown to ask for input. For example, for each OptionMenu, if option 1 is selected, then 3 labels and entries are created, and if option 2 is selected, only 2 labels and entries are created.

enter image description here

I tried to write the following code but it works only for the last OptionMenu. The Labels and Entries don't change at all when I change the first two OptionMenu. I tried to set a breakpoint at para.onchange() and it turns out that 'option1' is passed in the method whatever I select for the first two OptionMenu.

import tkinter as tk

window = tk.Tk()


class para:
    def __init__(self, master, option):
        self.master = master
        self.option = option
        if option == 'option1':
            self.nPara = 3
            self.textvariables = [tk.StringVar() for _ in range(self.nPara)]
            self.textvariables[0].set('para1')
            self.textvariables[1].set('para2')
            self.textvariables[2].set('para3')
        elif option == 'option2':
            self.nPara = 2
            self.textvariables = [tk.StringVar() for _ in range(self.nPara)]
            self.textvariables[0].set('para4')
            self.textvariables[1].set('para5')
        else:
            self.nPara = 0
            print('Error: invalid option')

        self.labels = [tk.Label(master, textvariable=self.textvariables[n])
                       for n in range(self.nPara)]
        self.entries = [tk.Entry(master) for _ in range(self.nPara)]
        for n in range(self.nPara):
            self.labels[n].pack()
            self.entries[n].pack()

    def onchange(self, master, option):
        for n in range(self.nPara):
            self.labels[n].pack_forget()
            self.entries[n].pack_forget()
        self.__init__(master, option)


nSec = 3
subframes = []
options = []
vars = []
paras = []
values = ['option1', 'option2']


for n in range(nSec):
    subframes.append(tk.Frame(window))
    vars.append(tk.StringVar(window))
    vars[n].set('option1')  # default option
    options.append(tk.OptionMenu(
        subframes[n], vars[n], *values,
        command=lambda x: paras[n].onchange(subframes[n], vars[n].get())))
    subframes[n].pack(side=tk.LEFT)
    options[n].pack()
    paras.append(para(subframes[n], vars[n].get()))

window.mainloop()

Any help will be appreciated. Thank you.


Edit:

I found that if I change the definition of onchange method to

    def onchange(self, option):
        for n in range(self.nPara):
            self.labels[n].pack_forget()
            self.entries[n].pack_forget()
        self.__init__(self.master, option)

and command of OptionMenu from command=lambda x: paras[n].onchange(subframes[n], vars[n].get()))) to command=paras[n].onchange, the problme is solved. But I have to put the following line

paras.append(para(subframes[n], vars[n].get()))

before options.append, which causes the OptionMenu is under the Labels and Entries when initializing.

0 Answers
Related