如何针对 Combobox 值的每次更改将函数唯一地绑定到 Ttk Combobox

How to bind Functions to Ttk Combobox uniquely for every change in value of Combobox

我想 link 一对唯一的组合框,例如一个组合框中的值取决于另一个组合框中的当前值。 但我没能让它发挥作用。只有一个组合框的初始值对另一个组合框的值有影响。 另外我希望每次更改组合框的值时都调用该函数。

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

对于cmb1中的Option1,我期望在cmb2中的结果为(1,2),在cmb1中的Option2中,结果为(3,4) 以及 cmb4 中的 (5,6) 用于 cmb3 中的 Option3 等等。

好吧,我只是尝试用 lambda: 抛出命令,但后来我得到了一个错误 <lambda> takes 0 ....but 1 was given 所以我只是在 lambda 函数中添加一个参数作为 lambda x: <function> 现在我得到了相同的结果预期结果,即代码现在可以完美运行,但即使我已经让它运行,但我仍然不完全理解它是如何解决的,如果有人能解释它会很有帮助。

Well i just tried throwing the command with lambda: but then i got an error takes 0 ....but 1 was given so i just add a argument in lambda function as lambda x: and now i get the same expected result i.e, the code works perfectly now, but even though i have got it to work but i still don't fully understand as to how it got solved

bind() 正在向您的 lambda 发送事件。那就是您的错误的来源。通过将 x 添加到您的 lambda 中,它通过允许一个位置参数来处理事件。如果没有正确格式化的 lambda,您的代码无法工作的原因是有括号 cmb2.config() 和其他配置。当您将一些 command/function 分配给 bind() 时,您需要保存对 command/function 的引用而不是调用它。这是通过不使用括号来完成的,但同时你不能传递参数。这就是 lambda 所允许的。

lambda 示例:

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

没有 lambda 的例子:

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