shubhasreepv
shubhasreepv

Reputation: 51

Can we nest two OptionMenu widgets in tkinter?

Just like the famous example of having Continent names in one dropdown and display country names related to selected Continent. How to achieve this using Tkinter? I have Continent list in first dropdown and list of all countries related to continents in the list. I would like to display country_11,country_12 when continent_1 is selected, similarly for other continents.

Here is the piece of code am working on -

import tkinter as tk
from tkinter import ttk
from tkinter import *

root = tk.Tk()
root.geometry('500x500')
#Label to Continent 
label_1 = tk.Label(root, text="Select the Continent", font = (8), bg = '#ffe1c4')
label_1.place(x = 120, y = 220)

# Continent selection - drop down
optionList1 = ["Continent1", "Continent2","Continent3"]
dropVar1 = StringVar()
dropMenu1 = ttk.OptionMenu(root, dropVar1 , *optionList1)
dropMenu1.place(x = 300, y = 220)

#Label to Select Country 
label_2 = tk.Label(root, text="Select the Country ", font = (8), bg = '#ffe1c4')
label_2.place(x = 120, y = 250)

# Country  name selection - drop down
optionList2 = ["Country_11", "Country_12", "Country_21","Country_22","Country_31","Country_32"]
dropVar2 = StringVar()
dropMenu2 = ttk.OptionMenu(root, dropVar2, *optionList2)
dropMenu2.place(x = 300, y = 250)

root.mainloop()

Would be great to have a solution to this as am not aware of all the attributes OptionMenu can have in Tkinter. Thanks in advance!!

Upvotes: 3

Views: 657

Answers (2)

jizhihaoSAMA
jizhihaoSAMA

Reputation: 12672

If your mean is to create two OptionMenu and it will show the different value when select different value in the first dropdown menu. You can try this:

import tkinter as tk
from tkinter import ttk
from tkinter import *

def func(selected_value): # the selected_value is the value you selected in the first drop down menu.
    dropMenu2.set_menu(*optionList2.get(selected_value))

root = tk.Tk()
root.geometry('500x500')
#Label to Continent
label_1 = tk.Label(root, text="Select the Continent", font = (8), bg = '#ffe1c4')
label_1.place(x = 120, y = 220)

# Continent selection - drop down
optionList1 = ["-","Continent1", "Continent2","Continent3"]
dropVar1 = StringVar()
dropMenu1 = ttk.OptionMenu(root, dropVar1 , *optionList1,command=func) # bind a command for the first dropmenu
dropMenu1.place(x = 300, y = 220)

#Label to Select Country
label_2 = tk.Label(root, text="Select the Country ", font = (8), bg = '#ffe1c4')
label_2.place(x = 120, y = 250)

# Country  name selection - drop down
optionList2 = { # when select different value,show the list.
    "Continent1": ["Country_11", "Country_12"],
    "Continent2": ["Country_21", "Country_22"],
    "Continent3": ["Country_31", "Country_32"]
}
dropVar2 = StringVar()
dropMenu2 = ttk.OptionMenu(root, dropVar2, "-")
dropMenu2.place(x = 300, y = 250)

root.mainloop()

Now it is: enter image description here

When select another value: enter image description here

(A suggestion:ttk.Combobox is prettier than OptionMenu,and using from tkinter import * is not a good practice.)

Upvotes: 4

Saad
Saad

Reputation: 3430

If you mean menu inside a menu then it is possible and very simple to do because the menu used in OptionMenu() is a tkinter Menu(), See the documentation of tkinter Menu.

We can access the Menu like so

Op = OptionMenu(root, var, 'Hello', 'HI', 'YOO')

# Op_Menu is the Menu() class used for OptionMenu
Op_Menu = Op['menu']

Here is a small example of nested menus in an option menu. When you select any of the countries inside any continent the text of optionmenu won't change so to fix that I used command argument and in each command argument of country I'm changing the value of the StringVar that is assigned to the optionmenu.

import tkinter as tk

root = tk.Tk()
svar = tk.StringVar()
svar.set('Antarctica')

Op = tk.OptionMenu(root, svar, svar.get())
OpMenu = Op['menu']
Op.pack()

Menu1 = tk.Menu(OpMenu)
OpMenu.add_cascade(label='Africa', menu= Menu1)
Menu1.add_command(label='Algeria', command=lambda: svar.set('Africa - Algeria'))
Menu1.add_command(label='Benin', command=lambda: svar.set('Africa - Benin'))

Menu2 = tk.Menu(Op['menu'])
OpMenu.add_cascade(label='Asia', menu= Menu2)
Menu2.add_command(label='China', command=lambda: svar.set('Asia - China'))
Menu2.add_command(label='India', command=lambda: svar.set('Asia - India'))

root.mainloop() 

Hope you find this helpful.

Upvotes: 2

Related Questions