Я пытаюсь создать графический интерфейс с раскрывающимися списками привязки, которые зависят от предыдущего раскрывающегося списка. Формат, который я пытаюсь достичь, выглядит следующим образом:
Код, над которым я работал, показан ниже. Это было получено из здесь:
import tkinter
from tkinter import ttk
root = tkinter.Tk()
'''
widgets are added here
'''
brands = ["Bugatti","BMW"]
models = [["Veyron","Golf"],
["330M"]]
Zip = [[["TEST1"],["TEST2"]],[["TEST3"]]]
car_brand = ttk.Combobox(root, width=37, value=(brands))
car_brand.grid(row=3, column=1, columnspan=2, padx=10, pady=2, sticky='w')
def callback(eventObject):
abc = eventObject.widget.get()
car = car_brand.get()
index=brands.index(car)
car_model.config(values=models[index])
car_model = ttk.Combobox(root, width=37)
car_model.grid(row=4, column=1, columnspan=2, padx=10, pady=2, sticky='w')
car_model.bind('<Button-1>', callback)
def callback2(eventObject):
abc = eventObject.widget.get()
y = car_model.get()
index=models.index(y)
xx.config(values=Zip[index])
xx = ttk.Combobox(root, width=37)
xx.grid(row=5, column=1, columnspan=2, padx=10, pady=2, sticky='w')
xx.bind('<Button-1>', callback2)
root.mainloop()
Я, вероятно, очень близок, но мне нужна помощь, чтобы заставить его работать.
Обновлять: Спасибо @JacksonPro за ваш ответ. Мне нужно было немного настроить его, чтобы учесть размещение сетки. См. ниже:
import tkinter as tk
from tkinter import ttk
cars = {"Bugatti":["Veyron","Golf"] ,"BMW":["330M"]}
_zip = [[["TEST1"],["TEST11"]],[["TEST2"],["Hello"],["World"]],["TEST3"]]
lst = [x for y in list(cars.values()) for x in y]
def change_dropdown(*args):
print("Chosen brand " + tkvar.get())
if args[0] == 'PY_VAR0':
for x, y in cars.items():
if tkvar.get() == x:
tkvar2.set(y[0])
popupMenu2.configure(values=y)
if args[0] == 'PY_VAR1':
for x, y in zip(lst, _zip):
if tkvar2.get() == x:
tkvar3.set(y[0])
popupMenu3.configure(values=y)
return
root = tk.Tk()
# canvas = tk.Canvas(root, height=500, width= 500, bg = "white")
root.geometry('500x100')
font = ("Courier", 16, "bold")
# canvas.pack()
tkvar = tk.StringVar(root)
tkvar.trace('w', change_dropdown)
tkvar2 = tk.StringVar(root)
tkvar2.trace('w', change_dropdown)
tkvar3 = tk.StringVar(root)
labelTop = tk.Label(root, text = "Select a State")
labelTop.grid(column=0, row=0)
popupMenu1 = ttk.Combobox(root, textvariable=tkvar, values=list(cars.keys()))
popupMenu1.grid(row=0, column=1)
# popupMenu1.pack()
popupMenu2 = ttk.Combobox(root, textvariable=tkvar2, values=[])
popupMenu2.grid(row=1, column=1)
# popupMenu2.pack()
popupMenu3 = ttk.Combobox(root, textvariable=tkvar3, values=[])
popupMenu3.grid(row=2, column=1)
# popupMenu3.pack()
root.mainloop()
Нет связи между state и CBSA, а также между CBSA и Zip. Так как же CBSA может зависеть от state, а Zip — от CBSA?
Обновленный вопрос основан на более близкой рабочей модели, которая больше соответствует моему общему замыслу. Необходимо, чтобы записи «Zip» заполнялись в третьем раскрывающемся списке на основе выбора второго раскрывающегося списка. Здесь мне нужна помощь.






Вот решение, которое вы можете улучшить, добавив также почтовый индекс.
import tkinter as tk
from tkinter import ttk
cars = {"Bugatti":["Veyron","Golf"] ,"BMW":["330M"]}
def change_dropdown(*args):
print("Chosen brand " + tkvar.get())
for x, y in cars.items():
if tkvar.get() == x:
tkvar2.set(y[0])
popupMenu2.configure(values=y)
root = tk.Tk()
canvas = tk.Canvas(root, height=500, width= 500, bg = "white")
canvas.pack()
tkvar = tk.StringVar(root)
tkvar2 = tk.StringVar(root)
tkvar3 = tk.StringVar(root)
popupMenu1 = ttk.Combobox(canvas, textvariable=tkvar, values=list(cars.keys()))
popupMenu1.pack()
popupMenu1.bind('<<comboboxselected>>', change_dropdown)
popupMenu2 = ttk.Combobox(canvas, textvariable=tkvar2, values=[])
popupMenu2.pack()
popupMenu1.bind('<<comboboxselected>>', change_dropdown)
popupMenu3 = ttk.Combobox(canvas, textvariable=tkvar3, values=[])
popupMenu3.pack()
root.mainloop()
Обновлять:
вот полностью рабочий код:
import tkinter as tk
from tkinter import ttk
cars = {"Bugatti":["Veyron","Golf"] ,"BMW":["330M"]}
_zip = [["TEST1"],["TEST2"],["TEST3"]]
lst = [x for y in list(cars.values()) for x in y]
def change_dropdown(*args):
print("Chosen brand " + tkvar.get())
if args[0] == 'PY_VAR0':
for x, y in cars.items():
if tkvar.get() == x:
tkvar2.set(y[0])
popupMenu2.configure(values=y)
if args[0] == 'PY_VAR1':
for x, y in zip(lst, _zip):
if tkvar2.get() == x:
tkvar3.set(y[0])
popupMenu3.configure(values=y)
return
root = tk.Tk()
canvas = tk.Canvas(root, height=500, width= 500, bg = "white")
canvas.pack()
tkvar = tk.StringVar(root)
tkvar.trace('w', change_dropdown)
tkvar2 = tk.StringVar(root)
tkvar2.trace('w', change_dropdown)
tkvar3 = tk.StringVar(root)
popupMenu1 = ttk.Combobox(canvas, textvariable=tkvar, values=list(cars.keys()))
popupMenu1.pack()
popupMenu2 = ttk.Combobox(canvas, textvariable=tkvar2, values=[])
popupMenu2.pack()
popupMenu3 = ttk.Combobox(canvas, textvariable=tkvar3, values=[])
popupMenu3.pack()
root.mainloop()
Спасибо @JacksonPro! Это было очень полезно. Мне пришлось внести небольшие изменения, чтобы иметь несколько вариантов для 3-го раскрывающегося списка; например: _zip = [[["TEST1"],["TEST11"]],[["TEST2"],["Hello"],["World"]],["TEST3"]]. Но это помогает мне получить общую структуру, которую я ищу.
Я сделал некоторые дальнейшие изменения; см. раздел обновления в исходном сообщении. Мне нужно было учесть размещение сетки, что я и сделал, изменив ваш ответ.
@AndrewHicks вам нужно указать вес строки и столбца 1: tk.Grid.rowconfigure(root, (0,1,2), weight=1) tk.Grid.columnconfigure(root, (0,1,2), weight=1)
Таким образом, это помогает расставить их и изменить их размер в зависимости от размера окна? Это довольно аккуратно! Спасибо!
Поэтому, когда я запускаю это дважды, при втором запуске 2-й и 3-й раскрывающиеся списки пусты. Единственный обходной путь, который я нашел, - это сбросить ядро (с помощью Jupyter Notebooks). Есть идеи, почему это так?
@AndrewHicks У меня это работает нормально. Я не использую Jupyter Notebook, поэтому не знаю, в чем проблема.
О... только что преобразовал мой файл .ipynb в файл .py, и он работает.
Я задал уточняющий вопрос. Будем очень признательны за любое ваше понимание: stackoverflow.com/questions/65387049/…
Так в чем именно ваша проблема?