'Saving variable from drop down menu command with lambda function in Tkinter
I want to extract the selected data from a drop down menu in Tkinter. The drop down menu changes based on a previous drop down menu selection.
Basically, how do I save a variable from a lambda function?
I've tried declaring a global variable, and dictionary value but the problem still is that I am overwriting the original drop down menu in my function and the code is still reading the value of the original drop down. Ideally, the code would just update the actual drop down list and not overwrite the original one. Apologies for my clunky, un-pythonic code.
import tkinter as tk
HEIGHT = 500
WIDTH = 500
root = tk.Tk()
canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()
subframe = tk.Frame(root, bg = 'gray', bd = 10)
subframe.place(relx = 0.05, rely = 0.05, relwidth = 0.9, relheight = 0.9)
subframe.rowconfigure(tuple(range(4)), weight = 1)
subframe.columnconfigure(tuple(range(4)), weight = 1)
inputs = {} ### dictionary for saved label *** I know there HAS to be a better way
### --- dropdown1 Input
label10 = tk.Label(subframe, text = 'Label 1', font = ('Century', 12), bg = 'gray', fg = 'white')
label10.grid(row = 1, column = 0, sticky = 'ew', padx = 5, pady = 5)
dropdown1_ID_series = ['A', 'B', 'C']
#global dropdown2_ID_var
def update_test_data_dropdown(dropdown1ID):
if dropdown1ID == 'C':
dropdown2_ID_series = ['1', '2', '3']
dropdown2_ID_var = tk.StringVar(root)
dropdown2_ID_var.set(dropdown2_ID_series[0])
dropdown2_ID_entry = tk.OptionMenu(subframe, dropdown2_ID_var, *dropdown2_ID_series)
dropdown2_ID_entry.config(width=10)
dropdown2_ID_entry.grid(row = 2, column = 1, sticky = 'ew', padx = 5, pady = 5)
inputs['dropdown2'] = dropdown2_ID_var.get()
print (inputs['dropdown2'])
else:
dropdown2_ID_series = ['4', '5','6']
dropdown2_ID_var = tk.StringVar(root)
dropdown2_ID_var.set(dropdown2_ID_series[0])
dropdown2_ID_entry = tk.OptionMenu(subframe, dropdown2_ID_var, *dropdown2_ID_series)
dropdown2_ID_entry.config(width=10)
dropdown2_ID_entry.grid(row = 2, column = 1, sticky = 'ew', padx = 5, pady = 5)
inputs['dropdown2'] = dropdown2_ID_var.get()
return dropdown2_ID_var ## need to figure out how to export dropdown2_ID_var
dropdown1_ID_var = tk.StringVar(root)
dropdown1_ID_var.set(dropdown1_ID_series[0])
dropdown1_ID_entry = tk.OptionMenu(subframe, dropdown1_ID_var, *dropdown1_ID_series, command = lambda x: update_test_data_dropdown(x))
dropdown1_ID_entry.config(width=10)
dropdown1_ID_entry.grid(row = 1, column = 1, sticky = 'ew', padx = 5, pady = 5)
### --- dropdown 2 input
label20 = tk.Label(subframe, text = 'Label 2', font = ('Century', 12), bg = 'gray', fg = 'white')
label20.grid(row = 2, column = 0, sticky = 'ew', padx = 5, pady = 5)
dropdown2_ID_series = ['D', 'E', 'F']
dropdown2_ID_var = tk.StringVar(root)
dropdown2_ID_var.set(dropdown2_ID_series[0])
dropdown2_ID_entry = tk.OptionMenu(subframe, dropdown2_ID_var, *dropdown2_ID_series)
dropdown2_ID_entry.config(width=10)
dropdown2_ID_entry.grid(row = 2, column = 1, sticky = 'ew', padx = 5, pady = 5)
inputs['dropdown2'] = dropdown2_ID_var.get()
print (inputs['dropdown2'])
def submit():
label11 = tk.Label(subframe, text = dropdown1_ID_var.get(), font = ('Century', 12), bg = 'gray', fg = 'white')
# label22 = tk.Label(subframe, text = dropdown2_ID_var.get(), font = ('Century', 12), bg = 'gray', fg = 'white')
label22 = tk.Label(subframe, text = inputs['dropdown2'], font = ('Century', 12), bg = 'gray', fg = 'white')
label11.grid(row = 1, column = 3, padx = 5, pady = 5)
label22.grid(row = 2, column = 3, padx = 5, pady = 5)
### --- RUN BUTTON
button = tk.Button(subframe, text = 'SUBMIT', font = ('Century', 12, 'bold'), command = lambda: submit())
button.grid(row = 3, column = 3, ipadx = 20, padx = 5, pady = 15)
root.mainloop()
When hitting SUBMIT on the above code, I want the selected value in the dropdowns to print next to the drop down.
Solution 1:[1]
I figured out a better way to update the drop down list by adding the optionmenu entry and variable to the function, deleting the original list, and editing through 'menu' and add_command. The two tricky/annoying things is having to create a loop to add the new list values individually then most importantly using tk._setit() to have the values actually selectable. I would be happy to find out if there is a better way but this at least works.
import tkinter as tk
HEIGHT = 500
WIDTH = 500
root = tk.Tk()
canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()
subframe = tk.Frame(root, bg = 'gray', bd = 10)
subframe.place(relx = 0.05, rely = 0.05, relwidth = 0.9, relheight = 0.9)
subframe.rowconfigure(tuple(range(4)), weight = 1)
subframe.columnconfigure(tuple(range(4)), weight = 1)
### --- dropdown1 Input
label10 = tk.Label(subframe, text = 'Label 1', font = ('Century', 12), bg = 'gray', fg = 'white')
label10.grid(row = 1, column = 0, sticky = 'ew', padx = 5, pady = 5)
dropdown1_ID_series = ['A', 'B', 'C']
def update_test_data_dropdown(dropdown1ID, dropdown2_ID_entry, dropdown2_ID_var):
if dropdown1ID == 'C':
dropdown2_ID_series2 = ['1', '2', '3']
dropdown2_ID_entry['menu'].delete(0,'end')
for v in dropdown2_ID_series2:
dropdown2_ID_entry['menu'].add_command(label = v, command= tk._setit(dropdown2_ID_var, v))
else:
dropdown2_ID_series2 = ['4', '5','6']
dropdown2_ID_entry['menu'].delete(0,'end')
for v in dropdown2_ID_series2:
dropdown2_ID_entry['menu'].add_command(label = v, command= tk._setit(dropdown2_ID_var, v))
dropdown2_ID_var.set(dropdown2_ID_series2[0])
return dropdown2_ID_var ## need to figure out how to export dropdown2_ID_var
dropdown1_ID_var = tk.StringVar(root)
dropdown1_ID_var.set(dropdown1_ID_series[0])
dropdown1_ID_entry = tk.OptionMenu(subframe, dropdown1_ID_var, *dropdown1_ID_series, command = lambda x: update_test_data_dropdown(x, dropdown2_ID_entry, dropdown2_ID_var))
dropdown1_ID_entry.config(width=10)
dropdown1_ID_entry.grid(row = 1, column = 1, sticky = 'ew', padx = 5, pady = 5)
### --- dropdown 2 input
label20 = tk.Label(subframe, text = 'Label 2', font = ('Century', 12), bg = 'gray', fg = 'white')
label20.grid(row = 2, column = 0, sticky = 'ew', padx = 5, pady = 5)
dropdown2_ID_series = ['D', 'E', 'F']
dropdown2_ID_var = tk.StringVar(root)
dropdown2_ID_var.set(dropdown2_ID_series[0])
dropdown2_ID_entry = tk.OptionMenu(subframe, dropdown2_ID_var, *dropdown2_ID_series)
dropdown2_ID_entry.config(width=10)
dropdown2_ID_entry.grid(row = 2, column = 1, sticky = 'ew', padx = 5, pady = 5)
def submit():
label11 = tk.Label(subframe, text = dropdown1_ID_var.get(), font = ('Century', 12), bg = 'gray', fg = 'white')
label22 = tk.Label(subframe, text = dropdown2_ID_var.get(), font = ('Century', 12), bg = 'gray', fg = 'white')
label11.grid(row = 1, column = 3, padx = 5, pady = 5)
label22.grid(row = 2, column = 3, padx = 5, pady = 5)
### --- RUN BUTTON
button = tk.Button(subframe, text = 'SUBMIT', font = ('Centur', 12, 'bold'), command = lambda: submit())
button.grid(row = 3, column = 3, ipadx = 20, padx = 5, pady = 15)
root.mainloop()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Heather B. |
