Tkinter的 Combobox绑定 <> 在初始化时会导致KeyError: ' '

编程语言 2026-07-12

我在尝试编写一个用于计算线径、保险丝尺寸和电流额定值的程序。

我有多个框架,每个框架都有其特定的计算。问题出现在单位转换框架。这里的目标是把AWG转换为mm²,或反之。

当我在组合框中选择一个值(对应我要从中转换的单位)时,我希望下面的 'result_label' 显示另一单位的转换值。

下面是我尝试的:

import tkinter as tk
from tkinter import ttk

options = {'padx': 10, 'pady': 5}
uitk_options = {'borderwidth': 5, 'relief': 'sunken'}

class UnitFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self.awg_dict = {'20': '0.50', '18': '0.75', '16': '1.50', '14': '2.50', '12': '4.00', '10': '6.00', '8': '10.00',
                         '6': '13.30', '4': '21.10', '2': '33.60', '0': '53.50', '00': '67.40', '000': '85.00', '0000': '107.20'}
        self.mm2_dict = {v: k for k, v in self.awg_dict.items()}

        #AWG to mm2
        self.awg_label = ttk.Label(self, text = 'AWG: ')
        self.awg_label.grid(column = 0, row = 0, **options)

        self.sel_awg = tk.StringVar()
        self.awg_comb = ttk.Combobox(self, textvariable = self.sel_awg)
        self.awg_comb['values'] = list(self.awg_dict.keys()); self.awg_comb['state'] = 'readonly'
        self.awg_comb.bind('<<ComboboxSelected>>', self.calculate(self.awg_dict, self.sel_awg.get()))
        self.awg_comb.grid(column = 1, row = 0, **options)

        self.awg_res_label = ttk.Label(self, text = 'MM2: ')
        self.awg_res_label.grid(column = 0, row = 1, **options)

        self.awg_uitk_label = ttk.Label(self, **uitk_options)
        self.awg_uitk_label.grid(column = 1, row = 1, **options)


        #mm2 to AWG
        self.mm2_label = ttk.Label(self, text = 'MM2: ')
        self.mm2_label.grid(column = 2, row = 0, **options)

        self.sel_mm2 = tk.StringVar()
        self.mm2_comb = ttk.Combobox(self, textvariable = self.sel_mm2)
        self.mm2_comb['values'] = list(self.mm2_dict.keys()); self.mm2_comb['state'] = 'readonly'
        self.mm2_comb.bind('<<ComboboxSelected>>', self.calculate(self.mm2_dict, self.sel_mm2.get()))
        self.mm2_comb.grid(column = 3, row = 0, **options)

        self.mm2_res_label = ttk.Label(self, text = 'AWG: ')
        self.mm2_res_label.grid(column = 2, row = 1, **options)

        self.mm2_uitk_label = ttk.Label(self, **uitk_options)
        self.mm2_uitk_label.grid(column = 3, row = 1, **options)


        self.grid(row = 0, column = 0, sticky = 'nsew')


    def calculate(self, dict_, key_):
        self.val = dict_[key_]

        if dict_ == self.awg_dict:
            self.awg_uitk_label.configure(text = self.val)
        else:
            self.mm2_uitk_label.configure(text = self.val)


class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title("Wiresize calculator")
        self.resizable(False, False)



if __name__ == "__main__":
    app = App()
    unit_frame = UnitFrame(app)

    app.mainloop()

所以我有两个组合框和两个字典,取决于我想进行哪种转换。

其中 'keys' 是给定单位的数值,'values' 是另一单位中对应的数值。

然后我定义了一个名为calculate的函数,它把我想使用的字典和要转换的给定值作为参数。key_ 参数由绑定到组合框的textvariable定义。在函数中我配置应显示结果的标签的文本。

这个函数我绑定到了 '<>' 事件。

用这段代码运行脚本时我会得到KeyError: ' '。我猜是因为此时组合框还没有选中任何项,key_ 参数是一个空字符串,所以Python找不到字典中的这个键,因为它不存在。

在对我的问题进行回顾时,有人指出我的问题是因为我的绑定直接调用了self.calculate函数,但我不知道在仅仅调用一个引用时如何把所需的值传递给参数。

self.awg_comb.bind('<<ComboboxSelected>>', self.calculate(self.awg_dict, 
                                                          self.sel_awg.get()))

我猜我的问题可以通过在self.calculate函数中使用一个条件语句来检查绑定到单选按钮的文本变量的值,从而确定要进行哪种转换,这样就不需要传参。不过为了可用性考虑,如上所述,我仍然希望在我在combobox中选择要转换的目标值时,程序能够立即在结果标签中显示转换后的值。

在这里能否有人给我指条正确的方向?

顺便说一句,这是我在这里的第一条提问,请告诉我如果有更好地表述问题的方式!

解决方案

你可以把所有逻辑放在 calculate() 函数里面:

  • 使用 event.widget 来确定是哪一个组合框触发了事件
  • 根据上述结果更新相应的标签
def __init__(self, parent):
    ...
    self.awg_comb.bind('<<ComboboxSelected>>', self.calculate)
    ...
    self.mm2_comb.bind('<<ComboboxSelected>>', self.calculate)
    ...

def calculate(self, event):
    if event.widget is self.awg_comb:
        val = self.awg_dict[self.sel_awg.get()]
        self.awg_uitk_label.configure(text=val)
    else:
        val = self.mm2_dict[self.sel_mm2.get()]
        self.mm2_uitk_label.configure(text=val)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章