首页 > 解决方案 > 使用单个函数更改 tkinter 中多个 Checkbutton 的值

问题描述

我正在尝试使用 tkinter 为我正在工作的项目构建我的第一个 GUI。我有多对相互依赖的复选按钮(在下面的示例中标记为 Rule 和 Trace)。默认情况下,所有规则检查按钮都被选中,而所有跟踪检查按钮都未选中。如果我想关闭特定的规则检查按钮,它应该变成红色,表示它未被选中(或关闭)。如果再次单击,它应该变成绿色,表示它已被选中(或打开)。我已经编写了一个函数checkbutton_state来处理这个问题。下面是我正在尝试做的一个工作示例。但我的问题是,此功能仅适用于规则 1 开/关检查按钮。我怎样才能概括它,以便我可以对所有规则检查按钮使用相同的功能?

此外,当特定规则关闭时,其对应的跟踪检查按钮应自动关闭,用户不应将其打开。如果打开了规则检查按钮,则应关闭相应的检查按钮,但用户应该能够在需要时将其打开。

我曾尝试使用 'lambda' 方法来尝试概括该功能,但不起作用。为了自动更改“跟踪”检查按钮的状态,我尝试使用该toggle()功能,但不知何故它没有给我想要的结果。我一整天都在努力寻找解决方案。任何有关我如何进行此操作的指导将不胜感激。

我的 Python 版本是 3.7.1,操作系统是 Windows 10(64 位)。

# Import requrired libraries/packages
from tkinter import Tk, Checkbutton, IntVar

# Create intance of tkinter
root = Tk()

# Define variables
rule1_on_choice = IntVar()
rule1_trace_choice = IntVar()
rule2_on_choice = IntVar()
rule2_trace_choice = IntVar()

# Create first set of checkbutton
# The 'trace' checkbutton is dependent on the 'on' checkbutton
# If the 'on' checkbutton is turned ON, 'trace' checkbutton should be turned off but user should be able to turn it on again
# If the 'on' checkbutton is turned OFF, 'trace' checkbutton should also be turned off but user should not be able to turn it on
rule1_on_checkbutton = Checkbutton(root, text = "Rule 1 ON", indicatoron = 0, bg = "green", variable = rule1_on_choice, onvalue = 1, offvalue = 0, selectcolor = "green")
rule1_trace_checkbutton = Checkbutton(root, text = "Rule 1 Trace", indicatoron = 0, bg = "red", variable = rule1_trace_choice, onvalue = 1, offvalue = 0, selectcolor = "red")

# Create second set of checkbuttons
rule2_on_checkbutton = Checkbutton(root, text = "Rule 2 ON", indicatoron = 0, bg = "green", variable = rule2_on_choice, onvalue = 1, offvalue = 0, selectcolor = "green")
rule2_trace_checkbutton = Checkbutton(root, text = "Rule 2 Trace", indicatoron = 0, bg = "red", variable = rule2_trace_choice, onvalue = 1, offvalue = 0, selectcolor = "red")

# The 'on' checkbuttons are turned on by default
# The 'trace' checkbuttons are turned off by default
rule1_on_checkbutton.select()
rule1_trace_checkbutton.deselect()
rule2_on_checkbutton.select()
rule2_trace_checkbutton.deselect()

rule1_on_checkbutton.pack()
rule1_trace_checkbutton.pack()
rule2_on_checkbutton.pack()
rule2_trace_checkbutton.pack()

# Function to change text and color of checkbutton
# If a Rule checkbutton is clicked, should turn green whith text showing "ON"
# The same checkbutton is clicked, it should now turn red with text showing "OFF"
def checkbutton_state(event = None):

    if rule1_on_choice.get() == 1:
        rule1_on_checkbutton.configure(text = "Rule 1 OFF", bg = "red", fg = "grey")

    else:
        rule1_on_checkbutton.configure(text = "Rule 1 ON", bg = "green", fg = "white")

# Binding function to Rule 1 'on' checkbutton
rule1_on_checkbutton.bind("<Button-1>", checkbutton_state)

root.mainloop()

标签: pythonpython-3.xtkinter

解决方案


不使用 . 很难完全概括您的功能lambda。您可以执行以下操作:

def checkbutton_state(event=None):
    if rule1_on_choice.get() == 1:
        event.widget.configure(text = event.widget['text'][0:6] + " OFF", bg = "red", fg = "grey")

    else:
        event.widget.configure(text = event.widget['text'][0:6] + " ON", bg = "green", fg = "white")

# Binding function to Rule 1 'on' checkbutton
rule1_on_checkbutton.bind("<Button-1>", checkbutton_state)
rule2_on_checkbutton.bind("<Button-1>", checkbutton_state)

如果您还想概括“rule1_on_choice”,那么您必须选择lambda,特别是对于您在问题第二部分中讨论的算法。以下代码完全概括 checkbutton_state

# Using lambda
def checkbutton_state_lambda(event, rule_on_choice, text_desc):
    if rule_on_choice.get() == 1:
        event.widget.configure(text = text_desc + " OFF", bg = "red", fg = "grey")

    else:
        event.widget.configure(text = text_desc + " ON", bg = "green", fg = "white")

# Binding function to Rule 1 'on' checkbutton
rule1_on_checkbutton.bind("<Button-1>", lambda event, a=rule1_on_choice, b="Rule 1": checkbutton_state_lambda(event, a, b))
rule2_on_checkbutton.bind("<Button-1>", lambda event, a=rule2_on_choice, b="Rule 2": checkbutton_state_lambda(event, a, b))

要禁用按钮,您应该设置stateDISABLED。您可以将“跟踪”按钮作为参数传递给“规则”按钮(单击时)并相应地修改其状态。

PS:我最好采用面向类的理念,在这种理念下,​​您可以更自由地使用self.


推荐阅读