首页 > 解决方案 > 如何将返回键绑定到多个 tkinter 检查按钮

问题描述

我正在设计一个 Tkinter GUI,它使用 Checkbuttons 来显示系统上可用的串行端口。用户将能够检查他们想要连接的任何端口,并且应该能够通过单击他们想要的复选框来执行此操作,或者通过按 Tab 键导航到每个 Checkbutton 然后按 Return 键来选择/取消选择他们想要的每一个。我遇到了一个错误。除了选项卡导航外,一切正常。在使用 Tab 键浏览我的 GUI 的字段时,一旦我按 Tab 进入 COM1(左)并按 Enter,它只会打开和关闭 COM3。然后,当我再次按 Tab 进入 COM3(右)时,COM3 仍会切换。我想要的是突出显示的任何字段都绑定到 Return 键。使用下面的示例,当 COM1 突出显示时,

COM1 突出显示时的状态选择 COM3 时的状态

我的函数接受一个值列表和一个框架对象,为列表中的每个值创建 Checkbutton,将 Checkbutton 附加到列表中,然后返回它。在我的照片中,列表是[COM1, COM3]

def make_checkboxes(frame, checkbox_list):
    """
    Description:            Make a series of Checkboxes for each value in the passed in list
    :param frame:           frame where all checkboxes will be placed
    :param checkbox_list:   list of values that each need a checkbox
    :return:                a checkbox entry list
    """
    boolean_list = []
    check_box = {}
    created_check_boxes = []
    for value in checkbox_list:
        # Create boolean for the current checkbox, set it to off
        boolean = IntVar()
        boolean.set(0)
        # Create checkbox with boolean that toggles it
        check_box = Checkbutton(frame, text=value, variable=boolean)
        check_box.pack()
        check_box.bind('<Return>', lambda e: toggle_check_box(boolean))
        created_check_boxes.append(check_box[value])
    return created_check_boxes

def toggle_check_box(check_box_obj):
    """
    Description:        Toggles a check box on and off when <Return> key is pressed
    :param boolean:     The current state of a checkbox 
    """
    if check_box_obj.get() == 1:
        check_box_obj.set(0)
    elif check_box_obj.get() == 0:
        check_box_obj.set(1)

标签: pythontkinter

解决方案


有两个问题:

  1. 您的代码显示了常见的“lambda-in-a-loop”问题,其中函数在执行时lambda使用变量值,而不是在定义时,即无论单击哪个按钮,都将具有最后一次迭代的值环形boolean

  2. 您想要通过绑定实现的已经是按 Space 和 Return 键的标准行为,即使用您的bind,在解决上述问题后,您实际上将切换按钮两次,撤消效果。仅当您想用其他键切换键时才需要它,例如t(用于“切换”)(但这可能取决于操作系统)

(此外,您可能希望check_box[value] = ...将复选框存储在循环之前创建的字典中,但这可能只是一个错字。)

把它们放在一起,你可以试试这个(或者完全删除该行):

#         index     not space or enter    bind b here          use b here
check_box[value].bind('<t>', lambda e, b=boolean: toggle_check_box(b))

推荐阅读