Search code examples
pythonuser-interfacetkinteroptionmenu

More on Python TKinter Dynamic OptionMenu


I'm trying to modify the code here to have the user confirm the items selected from the optionmenus. If the user clicks on the Submit button, a message box should open prompting confirmation. Finally, I want the selected items to be returned to the program as variables so they can be used in other functions for further processing. However, my modification is not working; it just returns an empty window. Thoughts on what I am missing? Many thanks.

from tkinter import *
import tkinter.messagebox

class App(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.dict = {'Asia': ['Japan', 'China', 'Malasia'],
                     'Europe': ['Germany', 'France', 'Switzerland'],
                     'Africa': ['Nigeria', 'Kenya', 'Ethiopia']}
        self.variable_a = StringVar(self)
        self.variable_b = StringVar(self)
        self.variable_a.trace('w', self.updateoptions)
        self.optionmenu_a = OptionMenu(self, self.variable_a, *self.dict.keys())
        self.variable_a.set('Asia')
        self.optionmenu_a.pack()
        self.optionmenu_b = OptionMenu(self, self.variable_b, ())
        self.optionmenu_b.pack()
        self.btn = Button(self, text="Submit", width=8, command=self.submit)
        self.btn.pack()
        self.pack()

    def updateoptions(self, *args):
        countries = self.dict[self.variable_a.get()]
        self.variable_b.set(countries[0])
        menu = self.optionmenu_b['menu']
        menu.delete(0, 'end')
        for country in countries:
            menu.add_command(label=country, command=lambda country=country: self.variable_b.set(country))
    
    def submit(self, *args):
        var1 = self.variable_a.get()
        var2 = self.variable_b.get()
        if tkinter.messagebox.askokcancel("Selection", "Confirm selection: " + var1 + ' ' + var2):
            print(var1, var2) #Or can be other function for further processing
         

root = Tk()
app = App(root)
app.mainloop()

Python version 3.4.1

EDIT: The window now appears with the widgets. I had omitted self. in front of the button. I still get an error message which I am trying to sort out: AttributeError: 'App' object has no attribute 'optionmenu_b'


Solution

  • Here @sedeh, this works as you wanted it to. The error came not from your add ons, but I think from using from tkinter import * instead of import tkinter as tk, this is why when running your code the error comes up as soon as the tk window comes up.

    What I have done is taken the code from the link you gave, added what you did and it works with no error.

    import tkinter as tk
    import tkinter.messagebox
    
    class App(tk.Frame):
        def __init__(self, master):
            tk.Frame.__init__(self, master)
            self.dict = {'Asia': ['Japan', 'China', 'Malasia'],
                         'Europe': ['Germany', 'France', 'Switzerland'],
                         'Africa': ['Nigeria', 'Kenya', 'Ethiopia']}
            self.variable_a = tk.StringVar(self)
            self.variable_b = tk.StringVar(self)
            self.variable_a.trace('w', self.updateoptions)
            self.optionmenu_a = tk.OptionMenu(self, self.variable_a, *self.dict.keys())
            self.optionmenu_b = tk.OptionMenu(self, self.variable_b, '')
            self.variable_a.set('Asia')
            self.optionmenu_a.pack()
            self.optionmenu_b.pack()
            self.btn = tk.Button(self, text="Submit", width=8, command=self.submit)
            self.btn.pack()
            self.pack()
        def updateoptions(self, *args):
            countries = self.dict[self.variable_a.get()]
            self.variable_b.set(countries[0])
            menu = self.optionmenu_b['menu']
            menu.delete(0, 'end')
            for country in countries:
                menu.add_command(label=country, command=lambda country=country: self.variable_b.set(country))
    
        def submit(self, *args):
            var1 = self.variable_a.get()
            var2 = self.variable_b.get()
            if tkinter.messagebox.askokcancel("Selection", "Confirm selection: " + var1 + ' ' + var2):
                print(var1, var2) #Or can be other function for further processing
    
    root = tk.Tk()
    app = App(root)
    app.mainloop()
    

    I hope this helps you.