Как привязать функции к Ttk Combobox уникально для каждого изменения в значении Combobox - PullRequest
0 голосов
/ 10 октября 2019

Я хочу связать Combobox в паре однозначно, например, значения в Combobox зависят от текущего значения в другом Combobox. Но я не могу заставить его работать. Только начальное значение одного Combobox влияло на Значения в другом Combobox. Также Я хочу, чтобы функция вызывалась при каждом изменении значения в выпадающем списке.

import tkinter as tk
from tkinter import ttk

class Win(tk.Tk):
    opt_dic1 = {'Option1' : ['1', '2'], 'Option2' : ['3', '4']}
    opt_dic2 = {'Option3' : ['5', '6'], 'Option4' : ['7', '8']}
    def __init__(self):
        super().__init__()
        top = tk.Frame(self)
        btm = tk.Frame(self)
        cmb1 = ttk.Combobox(top, values = list(Win.opt_dic1.keys()))
        cmb2 = ttk.Combobox(top)
        cmb3 = ttk.Combobox(btm, values = list(Win.opt_dic2.keys()))
        cmb4 = ttk.Combobox(btm)
        top.pack(side = 'top')
        btm.pack(side = 'bottom')
        cmb1.pack(side = 'left')
        cmb2.pack(side = 'left')
        cmb3.pack(side = 'left')
        cmb4.pack(side = 'left')
        cmb1.current(0)
        cmb3.current(0)
        cmb1.bind('<<ComboboxSelected>>', cmb2.config(values = Win.opt_dic1[cmb1.get()]))
        cmb3.bind('<<ComboboxSelected>>', cmb4.config(values = Win.opt_dic2[cmb3.get()]))

if __name__ == '__main__':
    Win().mainloop()

Я ожидал результата как (1,2) в cmb2 для Option1 в cmb1, (3,4) в cmb2 для варианта 2 в cmb1 и (5,6) в cmb4 для варианта 3 в cmb3 и т. Д.

Ответы [ 2 ]

0 голосов
/ 10 октября 2019

Ну, я просто попытался бросить команду с лямбда-выражением: но потом я получил ошибку, принимает 0 ...., но было дано 1, поэтому я просто добавляю аргумент в лямбда-функцию как лямбда-x: и теперь я получаютот же ожидаемый результат, т. е. код теперь работает отлично, но хотя я заставил его работать, но я все еще не до конца понимаю, как его решить

Ваш lambda отправляетсясобытие по bind(). Вот откуда ваша ошибка. Добавив x к вашей лямбде, которая позаботилась о событии, разрешив один позиционный аргумент. Причина, по которой ваш код не работал без правильно отформатированной лямбды, заключается в наличии круглых скобок cmb2.config() и другой конфигурации. Когда вы присваиваете какой-либо команде / функции bind(), вам нужно сохранить ссылку на команду / функцию, а не вызывать ее. Это делается без использования скобок, но в то же время вы не можете передавать аргументы. Это то, что позволяет лямбда.

Пример с лямбдой:

import tkinter as tk
from tkinter import ttk


class Win(tk.Tk):
    opt_dic1 = {'Option1': ['1', '2'], 'Option2': ['3', '4']}
    opt_dic2 = {'Option3': ['5', '6'], 'Option4': ['7', '8']}

    def __init__(self):
        super().__init__()
        top = tk.Frame(self)
        btm = tk.Frame(self)
        cmb1 = ttk.Combobox(top, values=list(Win.opt_dic1.keys()))
        cmb2 = ttk.Combobox(top)
        cmb3 = ttk.Combobox(btm, values=list(Win.opt_dic2.keys()))
        cmb4 = ttk.Combobox(btm)
        top.pack(side='top')
        btm.pack(side='bottom')
        cmb1.pack(side='left')
        cmb2.pack(side='left')
        cmb3.pack(side='left')
        cmb4.pack(side='left')
        cmb1.current(0)
        cmb3.current(0)
        cmb1.bind('<<ComboboxSelected>>', lambda x: cmb2.config(values=Win.opt_dic1[cmb1.get()]))
        cmb3.bind('<<ComboboxSelected>>', lambda x: cmb4.config(values=Win.opt_dic2[cmb3.get()]))


if __name__ == '__main__':
    Win().mainloop()

Пример без лямбды:

import tkinter as tk
from tkinter import ttk


class Win(tk.Tk):
    opt_dic1 = {'Option1': ['1', '2'], 'Option2': ['3', '4']}
    opt_dic2 = {'Option3': ['5', '6'], 'Option4': ['7', '8']}

    def __init__(self):
        super().__init__()
        top = tk.Frame(self)
        btm = tk.Frame(self)
        self.cmb1 = ttk.Combobox(top, values=list(Win.opt_dic1.keys()))
        self.cmb2 = ttk.Combobox(top)
        self.cmb3 = ttk.Combobox(btm, values=list(Win.opt_dic2.keys()))
        self.cmb4 = ttk.Combobox(btm)
        top.pack(side='top')
        btm.pack(side='bottom')
        self.cmb1.pack(side='left')
        self.cmb2.pack(side='left')
        self.cmb3.pack(side='left')
        self.cmb4.pack(side='left')
        self.cmb1.current(0)
        self.cmb3.current(0)
        self.cmb1.bind('<<ComboboxSelected>>', self.config_cmb2)
        self.cmb3.bind('<<ComboboxSelected>>', self.config_cmb4)

    def config_cmb2(self, _=None):
        self.cmb2.config(values=Win.opt_dic1[self.cmb1.get()])

    def config_cmb4(self, _=None):
        self.cmb4.config(values=Win.opt_dic2[self.cmb3.get()])


if __name__ == '__main__':
    Win().mainloop()
0 голосов
/ 10 октября 2019

Ну, я просто попытался выдать команду с lambda:, но затем я получил ошибку <lambda> takes 0 ....but 1 was given, поэтому я просто добавил аргумент в лямбда-функцию как lambda x: <function>, и теперь я получаю тот же ожидаемый результат, т.е. код работает отличносейчас, но хотя я заставил его работать, но я до сих пор не до конца понимаю, как это удалось решить, было бы полезно, если бы кто-нибудь смог это объяснить.

...