Как изменить глобальную переменную с помощью функции на основе выбора Optionmenu

Я новичок в python и пытаюсь создать конфигуратор продукта, используя tkinter optionmenu. Мне нужно использовать несколько optionmenu, и каждое выбранное значение должно создавать следующий набор данных для следующего optionmenu. Я исследовал все, что я мог думать, чтобы сделать это правильно, но безрезультатно.

ПРИМЕЧАНИЕ: второй вариант меню находится в примечании, так как он не работает с текущей конфигурацией. Кроме того, потребуется всего 4 меню параметров, все они основаны на значениях, выбранных перед ними.

Отредактированный код:

from tkinter import *


def openForm():
    print('Open Form')
    return


def openParts():
    print('Open Parts')
    return


capChoice = ['No Lift Selected']


def capFilter(liftSelection):
    global capChoice
    if liftSelection == 'Arm':
        capChoice = ['50kg', '100kg', '200kg', '300kg']
    elif liftSelection == 'Arm (Food Grade)':
        capChoice = ['75kg']
    elif liftSelection == 'Rail':
        capChoice = ['125kg', '300kg']
    elif liftSelection == 'Drive':
        capChoice = ['125kg', '300kg']
    print(capChoice)


lengthChoice = ['No Capacity Selected']


def lengthFilter(lengthSelection):
    global lengthChoice
    if lengthSelection == '50kg' and capChoice == 'Arm':
        lengthChoice = ['3m']
    elif lengthSelection == '75kg':
        lengthChoice = ['4.2m']
    elif lengthSelection == '100kg' and capChoice == 'Arm':
        lengthChoice = ['3m', '4m', '5m']
    elif lengthSelection == '125kg':
        lengthChoice = ['N/A']
    elif lengthSelection == '200kg' and capChoice == 'Arm':
        lengthChoice = ['3m', '4m', '5m']
    elif lengthSelection == '300kg' and capChoice == 'Arm':
        lengthChoice = ['3m', '4m']
    elif lengthSelection == '300kg' and capChoice == 'Rail':
        lengthChoice = ['N/A']
    elif lengthSelection == '300kg' and capFilter() == 'Drive':
        lengthChoice = ['N/A']


app = Tk()
app.title('QL Form')
app.geometry('560x460+200+200')

menubar = Menu(app)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label='Form', command=openForm)
filemenu.add_command(label='Req Parts', command=openParts)
filemenu.add_separator()
filemenu.add_command(label='Quit', command=app.quit)
menubar.add_cascade(label='Page', menu=filemenu)

app.config(menu=menubar)

liftType = StringVar()
liftType.set('Lift Type')
files = ['Arm', 'Arm (Food Grade)', 'Rail', 'Drive']
liftDropDown = OptionMenu(app, liftType, *files, command=capFilter)
liftDropDown.pack()

liftCap = StringVar()
liftCap.set('Capacity')
capDropDown = OptionMenu(app, liftCap, *capChoice, command=lengthFilter)
capDropDown.pack()

liftLength = StringVar()
liftLength.set('Length')
capDropDown = OptionMenu(app, liftLength, *lengthChoice, command=lengthFilter)
capDropDown.pack()


app.mainloop()

Код перед:

from tkinter import *


def openForm():
    print('Open Form')
    return


def openParts():
    print('Open Parts')
    return


def capFilter(selection):
    global capChoice
    if selection == 'Arm':
        capChoice = ['50kg', '100kg', '200kg', '300kg']
    elif selection == 'Arm (Food Grade)':
        capChoice = ['75kg']
    elif selection == 'Rail':
        capChoice = ['125kg', '300kg']
    elif selection == 'Drive':
        capChoice = ['125kg', '300kg']
    print(capChoice)
    return capChoice



def lengthFilter(selection):
    if selection == '50kg' and capFilter() == 'Arm':
        lengthChoice = ['3m']
    elif selection == '75kg':
        lengthChoice = ['4.2m']
    elif selection == '100kg' and capFilter() == 'Arm':
        lengthChoice = ['3m', '4m', '5m']
    elif selection == '125kg':
        lengthChoice = ['N/A']
    elif selection == '200kg' and capFilter() == 'Arm':
        lengthChoice = ['3m', '4m', '5m']
    elif selection == '300kg' and capFilter() == 'Arm':
        lengthChoice = ['3m', '4m']
    elif selection == '300kg' and capFilter() == 'Rail':
        lengthChoice = ['N/A']
    elif selection == '300kg' and capFilter() == 'Drive':
        lengthChoice = ['N/A']
    return lengthChoice


app = Tk()
app.title('QL Form')
app.geometry('560x460+200+200')

menubar = Menu(app)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label='Form', command=openForm)
filemenu.add_command(label='Req Parts', command=openParts)
filemenu.add_separator()
filemenu.add_command(label='Quit', command=app.quit)
menubar.add_cascade(label='Page', menu=filemenu)

app.config(menu=menubar)

liftType = StringVar()
liftType.set('Lift Type')
files = ['Arm', 'Arm (Food Grade)', 'Rail', 'Drive']
liftDropDown = OptionMenu(app, liftType, *files, command=capFilter)
liftDropDown.pack()


'''
liftCap = StringVar()
liftCap.set('Capacity')
capDropDown = OptionMenu(app, liftCap, *capChoice, command=lengthFilter)
capDropDown.pack()
'''

app.mainloop()

person KundelJ    schedule 19.12.2017    source источник
comment
Просто измените глобальные значения с помощью функций вместо того, чтобы пытаться вернуться.   -  person Nae    schedule 19.12.2017
comment
Даже без возврата capChoice и lengthChoice не обновляются функциями. если я печатаю внутри функции, значение изменяется, но если я печатаю вне функции, даже после ее запуска значение остается исходным.   -  person KundelJ    schedule 19.12.2017
comment
функция, используемая в command= , bind() или after(), выполняется mainloop(), которая пропускает значение, возвращаемое из функции. Вы должны изменить глобальные переменные или обновить виджеты напрямую.   -  person furas    schedule 19.12.2017
comment
где вы печатаете capChoice вне функции? вы должны помнить, что все print() до mainloop() выполняются before окно создается, поэтому все виджеты пусты.   -  person furas    schedule 19.12.2017
comment
Код отредактирован для изменения глобальной переменной, но с проблемой, указанной в последнем комментарии.   -  person KundelJ    schedule 19.12.2017
comment
вы должны создать переменную capChoice, прежде чем использовать ее в OptionMenu - функция capFilter создаст/использует эти переменные намного позже. Но если вы измените значения в capChoice, это не изменит значения в OptionMenu, потому что OptionMenu только копирует значения из capChoice, а позже не использует эту переменную.   -  person furas    schedule 19.12.2017
comment
в отредактированном коде я сначала создал переменные, и Optionmenu должен запустить функцию и изменить ее значение, как только я выберу значение из Optionmenu, верно?   -  person KundelJ    schedule 19.12.2017


Ответы (1)


cap_dropdown копирует значения из cap_choice при запуске, но потом не использует их - поэтому, если вы даже измените значения в cap_choice, это не сработает.

Внутри cap_filter вы должны заменить элементы непосредственно в cap_dropdown.

import tkinter as tk

def cap_filter(selection):
    options = {
        'Arm': ['50kg', '100kg', '200kg', '300kg'],
        'Arm (Food Grade)': ['75kg'],
        'Rail': ['125kg', '300kg'],
        'Drive': ['125kg', '300kg'],
    }

    if selection in options:
        items = options[selection]    
    else:
        items = []
    print(items)    

    # remove old elements
    cap_dropdown['menu'].delete(0, 'end')

    # add new items
    for text in items:
        cap_dropdown['menu'].add_command(label=text, command=lambda arg=text:length_filter(arg))


def length_filter(selection):
    type_ = lift_type.get()

    if selection == '50kg' and type_ == 'Arm':
        length_choice = ['3m']
    elif selection == '75kg':
        length_choice = ['4.2m']
    elif selection == '100kg' and type_ == 'Arm':
        length_choice = ['3m', '4m', '5m']
    elif selection == '125kg':
        length_choice = ['N/A']
    elif selection == '200kg' and type_ == 'Arm':
        length_choice = ['3m', '4m', '5m']
    elif selection == '300kg' and type_ == 'Arm':
        length_choice = ['3m', '4m']
    elif selection == '300kg' and type_ == 'Rail':
        length_choice = ['N/A']
    elif selection == '300kg' and type_ == 'Drive':
        length_choice = ['N/A']
    else:
        length_choice = ['N/A']

    print(length_choice)

app = tk.Tk()

lift_type = tk.StringVar()
lift_type.set('Lift Type')
files = ['Arm', 'Arm (Food Grade)', 'Rail', 'Drive']

lift_dropdown = tk.OptionMenu(app, lift_type, *files, command=cap_filter)
lift_dropdown.pack()

lift_cap = tk.StringVar()
lift_cap.set('Capacity')
cap_choice = ['']

cap_dropdown = tk.OptionMenu(app, lift_cap, *cap_choice, command=length_filter)
cap_dropdown.pack()

app.mainloop()
person furas    schedule 19.12.2017
comment
Еще один вопрос: интересно, почему в дропбоксе не отображается емкость - person KundelJ; 19.12.2017