Tkinter Combobox Help

Having trouble making one combobox create the values for a second combobox. I have been googling methods to do this but it seems that there are so many methods that either are depreciated or i just cant get it work.

size_var = StringVar()
plant_type_var = StringVar()

plant_categories = {'container': ['quart', '1gal', '3gal', '5gal'], 'deciduous trees':['2"', '2.5"']}
ListB= plant_categories['container']

def getUpdateData(*args):
            sel = plant_type_var.get()
            
            if sel == 'container':
                ListB = plant_categories['container']
            elif sel == 'deciduous trees':
                ListB = plant_categories['deciduous_trees']
            plant_size.config(values=ListB)

        plant_type_var.trace_add('write', getUpdateData)

plant_type = ttk.Combobox(plant_window,  values = list(plant_categories.keys()), textvariable=plant_type_var).grid(row=grid_rows, column=2)
plant_size = ttk.Combobox(plant_window, textvariable=size_var, values=ListB).grid(row=grid_rows,column=3)

It seems like you’re trying to update the values of the second combobox (plant_size) based on the selection made in the first combobox (plant_type). There are a few issues in your code that need to be addressed.

  1. The variable ListB is being redefined in the local scope of the function getUpdateData, which doesn’t affect the global scope. You need to declare ListB as a global variable inside the function.
  2. The keys in your plant_categories dictionary are 'container' and 'deciduous trees', but you are trying to access 'deciduous_trees' in the getUpdateData function. Update it to 'deciduous trees'.

Here’s the corrected code:

import tkinter as tk
from tkinter import ttk

plant_window = tk.Tk()
grid_rows = 1

size_var = tk.StringVar()
plant_type_var = tk.StringVar()

plant_categories = {‘container’: [‘quart’, ‘1gal’, ‘3gal’, ‘5gal’], ‘deciduous trees’: [‘2"’, ‘2.5"’]}
ListB = plant_categories[‘container’]

def getUpdateData(*args):
global ListB # Declare ListB as a global variable
sel = plant_type_var.get()

if sel == 'container':
    ListB = plant_categories['container']
elif sel == 'deciduous trees':
    ListB = plant_categories['deciduous trees']

plant_size.config(values=ListB)

plant_type_var.trace_add(‘write’, getUpdateData)

plant_type = ttk.Combobox(plant_window, values=list(plant_categories.keys()), textvariable=plant_type_var)
plant_type.grid(row=grid_rows, column=2)

plant_size = ttk.Combobox(plant_window, textvariable=size_var, values=ListB)
plant_size.grid(row=grid_rows, column=3)

plant_window.mainloop()

This should work as expected, updating the values of plant_size based on the selection made in plant_type .

Hope this will help you.

Are you trying to do something like this?
When you create the combobox, you should seperate the grid into it’s own line eg
box = ttk.combobox()
box.grid()

When placing on the same line will cause it to not work correct.

# Do the imports
import tkinter as tk 
from tkinter import ttk 

# Function for updating 2nd combobox
def update(*args):

    # Clear 2nd combobox then populate based on index from 1st combobox
    box2.set('')
    value = int(box1.current())

    if value == 0:
       box2['values'] = box2_c1

    if value == 1:
        box2['values'] = box2_c2

    if value == 2:
        box2['values'] = box2_c3

    # Set default selection
    box2.current(0)

# Box1 content
box1_content = [f'Content {i}' for i in range(3)]

# Box2 contents
box2_c1 = [f'Some Content {i}' for i in range(20, 40)]

box2_c2 = [f'More Content {i}' for i in range (50, 100)]

box2_c3 = [f'Still Content {i}' for i in range (1001, 1020)]

# Create the tkinter window/widget
root = tk.Tk()
root['padx'] = 8
root['pady'] = 8

var = tk.StringVar()

# Create combobox 1
box1 = ttk.Combobox(root, textvariable=var)
box1['values'] = box1_content
box1.pack(side = 'left', expand=True, fill='x')

# Set default value
box1.current(0)

# Bind combobox to update function. This could also be done using trace
# Then you would not need to use bind
box1.bind('<<ComboboxSelected>>', lambda event: update())

# Create combobox 2
box2 = ttk.Combobox(root)
box2['values'] = box2_c1
box2.pack(side = 'left', expand=True, fill='x')

# Set default value for combobox 2
box2.current(0)

''' Commented out because of using bind
    If wanting to use trace, uncomment this line and comment out the bind line
    for box1 '''
# var.trace('w', update)
root.mainloop()

Thank you both for taking the time to help. I had to run 9ut for a bit but will try these when i get back.

Thanks again

Thank you for the help. I think i have it half right. For some reason i combined both of your answers and now it sort of works. The first two selections of plant_type box will work but the last 2 selections do not.

Not sure what i did and now when i removed one of the suggestion solutions, nothing works.

        plant_categories = {
            'container': ['quart', '1gal', '3gal', '5gal', '7gal', '10gal', '15gal', '25gal'], 
            'deciduous trees':['1.5"-2"', '2"-2.5"', '2.5"-3"', '3"-3.5"'], 
            'evergreen trees':["4'-5'", "5'-6'", "6'-7'", "7'-8'", "8'-9'", "9'-10'"],
            'shrubs': ['12"-15"', '15"-18"', '18"-24"', '24"-30"', '30"-36"', '36"-40"']}
        ListB= plant_categories['container']

        def updateBoxes(*args):
            plant_size.set('')
            value = int(plant_type.current())

            if value == 'container':
                plant_size['values'] = plant_categories['container']
            if value == 'deciduous trees':
                plant_size['values'] = plant_categories['deciduous trees']
            if value == 'evergreen trees':
                plant_size['values'] = plant_categories['evergreen trees']
            if value == 'shrubs':
                plant_size['values'] = plant_categories['shrubs']

        def getUpdateData(*args):
            global ListB
            sel = plant_type_var.get()
            
            if sel == 'container':
                ListB = plant_categories['container']
            elif sel == 'deciduous trees':
                ListB = plant_categories['deciduous trees']
            elif sel == 'evergreen trees':
                ListB == plant_categories['evergreen trees']
            elif sel == 'shrubs':
                ListB == plant_categories['shrubs']

            plant_size.config(values=ListB)

        plant_type_var.trace_add('write', getUpdateData)

        plant_type = ttk.Combobox(plant_window,  values = list(plant_categories.keys()), textvariable=plant_type_var)
        plant_type.grid(row=grid_rows, column=2)
        
        plant_type.bind("<<ComboboxSelected>>", lambda event: updateBoxes())
        plant_size = ttk.Combobox(plant_window, textvariable=size_var)
        plant_size.grid(row=grid_rows,column=3)

Is the dict keys, the selection for the first combobox and the list values for the 2nd combobox?

Yes thats what im trying

# Do the imports
import tkinter as tk 
from tkinter import ttk 

# Function for updating 2nd combobox
def update():
    print(box1.get())
    box2.set('')
    box2['values'] = plant_categories[box1.get()]
    box2.current(0)

plant_categories = {
            'container': ['quart', '1gal', '3gal', '5gal', '7gal', '10gal', '15gal', '25gal'], 
            'deciduous trees':['1.5"-2"', '2"-2.5"', '2.5"-3"', '3"-3.5"'], 
            'evergreen trees':["4'-5'", "5'-6'", "6'-7'", "7'-8'", "8'-9'", "9'-10'"],
            'shrubs': ['12"-15"', '15"-18"', '18"-24"', '24"-30"', '30"-36"', '36"-40"']}

# Create the tkinter window/widget
root = tk.Tk()
root['padx'] = 8
root['pady'] = 8

# Create combobox 1
box1 = ttk.Combobox(root)
box1['values'] = [key for key in plant_categories.keys()]
box1.pack(side = 'left', expand=True, fill='x')

# Set default value
box1.current(0)

# Bind combobox to update function.
box1.bind('<<ComboboxSelected>>', lambda event: update())

# Create combobox 2
 
box2 = ttk.Combobox(root)
box2['values'] = plant_categories['container']
box2.pack(side='left', expand=True, fill='x')
box2.current(0)

root.mainloop()

thank you so much. im still seeing how you did it. The only thing im really struggling with is

box1['values'] = [ key for key in plant_categories.keys()]

ive never used that type of statement before.

Thanks again

It’s list comprehension. Useful at times. It’s creating a list from the dict keys.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.