Как вы можете сделать 3 (или 4) вложенных связанных поля со списком, используя Tkinter в python?

Я пытаюсь создать графический интерфейс с раскрывающимися списками привязки, которые зависят от предыдущего раскрывающегося списка. Формат, который я пытаюсь достичь, выглядит следующим образом:

  1. Выберите {уровень 1}
  2. Выберите {уровень 2} — привязанный к уровню 1
  3. Выберите {уровень 3} - привязанный к уровню 2
  4. Выберите {уровень 4} - привязанный к уровню 3

Код, над которым я работал, показан ниже. Это было получено из здесь:

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()

Так в чем именно ваша проблема?

JacksonPro 17.12.2020 06:48

Нет связи между state и CBSA, а также между CBSA и Zip. Так как же CBSA может зависеть от state, а Zip — от CBSA?

acw1668 17.12.2020 06:58

Обновленный вопрос основан на более близкой рабочей модели, которая больше соответствует моему общему замыслу. Необходимо, чтобы записи «Zip» заполнялись в третьем раскрывающемся списке на основе выбора второго раскрывающегося списка. Здесь мне нужна помощь.

Andrew Hicks 17.12.2020 09:27
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот решение, которое вы можете улучшить, добавив также почтовый индекс.

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"]],["TE‌​ST3"]]. Но это помогает мне получить общую структуру, которую я ищу.

Andrew Hicks 17.12.2020 19:16

Я сделал некоторые дальнейшие изменения; см. раздел обновления в исходном сообщении. Мне нужно было учесть размещение сетки, что я и сделал, изменив ваш ответ.

Andrew Hicks 17.12.2020 19:42

@AndrewHicks вам нужно указать вес строки и столбца 1: tk.Grid.rowconfigure(root, (0,1,2), weight=1) tk.Grid.columnconfigure(root, (0,1,2), weight=1)

JacksonPro 18.12.2020 03:14

Таким образом, это помогает расставить их и изменить их размер в зависимости от размера окна? Это довольно аккуратно! Спасибо!

Andrew Hicks 18.12.2020 04:22

Поэтому, когда я запускаю это дважды, при втором запуске 2-й и 3-й раскрывающиеся списки пусты. Единственный обходной путь, который я нашел, - это сбросить ядро ​​(с помощью Jupyter Notebooks). Есть идеи, почему это так?

Andrew Hicks 18.12.2020 04:41

@AndrewHicks У меня это работает нормально. Я не использую Jupyter Notebook, поэтому не знаю, в чем проблема.

JacksonPro 18.12.2020 04:53

О... только что преобразовал мой файл .ipynb в файл .py, и он работает.

Andrew Hicks 18.12.2020 05:00

Я задал уточняющий вопрос. Будем очень признательны за любое ваше понимание: stackoverflow.com/questions/65387049/…

Andrew Hicks 21.12.2020 04:02

Другие вопросы по теме