I am trying to get multiple binding statements onto one combobox, but it is not working.
I have a tkinter window to enter data into a sql database with several dependent comboboxes to make the data entry easier in places that will cause fatal errors if the wrong thing is entered. The state name combobox will queue the state abbreviation in one combobox and another for national park names available in that state. The park chosen then triggers another combobox where the only option should be the park abbreviation. The problem I am having is with the binding of the state abbreviation and the park name comboboxes to the state combobox. They are in two separate statements, and I can only get one at a time to work. I have to comment out the state abbr bind in order to use the park name and park abbreviation comboboxes, or visa versa. Any ideas?
from tkinter import *
from tkinter import ttk
# list of states
states = ['Alaska', 'Arizona', 'Arkansas']
# dictionaries
STATE_DICT = {
'state_name': {
'AK': 'Alaska',
'AR': 'Arkansas',
'AZ': 'Arizona'}
}
PARKS_DICT = {
'state_name': {
'DENA': 'Alaska',
'GLBA': 'Alaska',
'KATM': 'Alaska',
'KEFJ': 'Alaska',
'HOSP': 'Arkansas',
'GRCA': 'Arizona',
'PEFO': 'Arizona',
'SAGU': 'Arizona'
},
'park_name': {
'DENA': 'Denali National Park',
'GLBA': 'Glacier Bay National Park',
'KATM': 'Katmai National Park',
'KEFJ': 'Kenai Fjords National Park',
'HOSP': 'Hot Springs National Park',
'GRCA': 'Grand Canyon National Park',
'PEFO': 'Petrified Forest National Park',
'SAGU': 'Saguaro National Park'}
}
root2 = Tk()
root2.title("data_entry_form")
root2.geometry("800x500")
state_name_label = Label(root2, text="State Name", width=20, font=("bold", 12),bd=1, relief="raised")
state_abbr_label = Label(root2, text="State Abbr", width=20, font=("bold", 12),bd=1, relief="raised")
park_name_label = Label(root2, text="Park Name", width=20, font=("bold", 12),bd=1, relief="raised")
park_abbr_label = Label(root2, text="Park Abbr", width=20, font=("bold", 12),bd=1, relief="raised")
nearest_city_label = Label(root2, text="Nearest City", width=20, font=("bold", 12),bd=1, relief="raised")
geo_location_label = Label(root2, text="Geo Location", width=20, font=("bold", 12),bd=1, relief="raised")
hike_name_label = Label(root2, text="Hike Name", width=20, font=("bold", 12),bd=1, relief="raised")
length_miles_label = Label(root2, text="Length in Miles", width=20, font=("bold", 12),bd=1, relief="raised")
elevation_gain_feet_label = Label(root2, text="Elevation in Feet", width=20, font=("bold", 12),bd=1, relief="raised")
nps_difficulty_rating_label = Label(root2, text="NPS Difficulty Rating", width=20, font=("bold", 12),bd=1, relief="raised")
route_type_label = Label(root2, text="Route Type", width=20, font=("bold", 12),bd=1, relief="raised")
# Data entry fields
hike_name_entry = Entry(root2,width=100)
nearest_city_entry = Entry(root2,width=50)
geo_location_entry = Entry(root2,width=50)
length_miles_entry = Entry(root2,width=50)
elevation_gain_feet_entry = Entry(root2,width=50)
# submit button
submitbutton = Button(root2, text='Submit New Hike!', width=20, bg="black", fg='white')
# comboboxes
def parks_list(e):
p=list()
x=list()
for key,value in PARKS_DICT['state_name'].items():
if value==state_combo.get():
p.append(key)
for k,v in PARKS_DICT['park_name'].items():
if k in p:
x.append(v)
park_combo.config(value=x)
def park_abb(e):
p=list()
for key,value in PARKS_DICT['park_name'].items():
if value==park_combo.get():
p.append(key)
park_abbr_combo.config(value=p)
def state_abb(e):
p=list()
for key,value in STATE_DICT['state_name'].items():
if value==state_combo.get():
p.append(key)
state_abbr_combo.config(value=p)
state_combo = ttk.Combobox(root2, value=states)
state_combo.current(0)
#state_combo.bind("<<ComboboxSelected>>", state_abb) #-have to # this out to get the other statement to work.
state_combo.bind("<<ComboboxSelected>>", parks_list)
state_abbr_combo = ttk.Combobox(root2, value=[" "])
state_abbr_combo.current(0)
park_combo = ttk.Combobox(root2, value=[" "])
park_combo.current(0)
park_combo.bind("<<ComboboxSelected>>", park_abb)
park_abbr_combo = ttk.Combobox(root2, value=[" "])
park_abbr_combo.current(0)
nps_difficulty_rating= ttk.Combobox(root2, value =range(1,6))
route_type_combo=ttk.Combobox(root2, value=['loop','out and back','point to point'])
# Grid placement
state_name_label.grid(row=1, column=0, padx=10, pady=10)
state_combo.grid(row=1, column=1, padx=10, pady=10)
state_abbr_label.grid(row=2, column=0, padx=10, pady=10)
state_abbr_combo.grid(row=2, column=1, padx=10, pady=10)
park_name_label.grid(row=3, column=0, padx=10, pady=10)
park_combo.grid(row=3, column=1, padx=10, pady=10)
park_abbr_label.grid(row=4, column=0, padx=10, pady=10)
park_abbr_combo.grid(row=4, column=1, padx=10, pady=10)
nearest_city_label.grid(row=5, column=0, padx=10, pady=10)
nearest_city_entry.grid(row=5, column=1, padx=10, pady=10)
geo_location_label.grid(row=6, column=0, padx=10, pady=10)
geo_location_entry.grid(row=6, column=1, padx=10, pady=10)
hike_name_label.grid(row=7, column=0, padx=10, pady=10)
hike_name_entry.grid(row=7, column=1, padx=10, pady=10)
length_miles_label.grid(row=8, column=0, padx=10, pady=10)
length_miles_entry.grid(row=8, column=1, padx=10, pady=10)
elevation_gain_feet_label.grid(row=9, column=0, padx=10, pady=10)
elevation_gain_feet_entry.grid(row=9, column=1, padx=10, pady=10)
nps_difficulty_rating_label.grid(row=10, column=0, padx=10, pady=10)
nps_difficulty_rating.grid(row=10, column=1, padx=10, pady=10)
route_type_label.grid(row=11, column=0, padx=10, pady=10)
route_type_combo.grid(row=11, column=1, padx=10, pady=10)
submitbutton.grid(row=12, column=1, padx=10, pady=10)
root2.mainloop()
While it's possible to do more than one binding, I see no advantage to doing so. Instead, create a function that calls the other functions.
def state_combo_changed(event):
state_abb(event)
parks_list(abb)
state_combo.bind("<<ComboboxSelected>>", state_combo_changed)
If you insist on doing two separate bindings you can set the add
attribute to True
:
state_combo.bind("<<ComboboxSelected>>", state_abb)
state_combo.bind("<<ComboboxSelected>>", parks_list, add=True)