Feb-16-2022, 10:20 PM
I modified my example to enable/disable a button based on the value of multiple checkboxes.
import tkinter as tk class Checkbox(tk.Checkbutton): """I add an IntVar to a check button""" var_types = {bool:tk.BooleanVar, int:tk.IntVar, float:tk.DoubleVar} def __init__(self, parent, x, y, onvalue=1, offvalue=0, **kwargs): self.variable = self.var_types.get(type(onvalue), tk.StringVar)(value=offvalue) super().__init__(parent, variable=self.variable, onvalue=onvalue, offvalue=offvalue, **kwargs) self.place(x=x, y=y) def value(self): return self.variable.get() def set_value(self, value): self.variable.set(value) class App(tk.Tk): def __init__(self, title=None, geometry="250x120", **kwargs): super().__init__(**kwargs) if geometry is not None: self.geometry(geometry) if title is not None: self.wm_title(title) self.checkboxes = [ Checkbox(self,10, 10, text="A"), Checkbox(self,10, 50, text="B"), Checkbox(self,10, 90, text="C") ] self.button = tk.Button(self, text="Push Me") self.button.place(x=100, y=10) for checkbox in self.checkboxes: checkbox.config(command = lambda: self.enable_control(self.button, self.checkboxes)) self.enable_control(self.button, self.checkboxes) def enable_control(self, control, checkboxes): if any(checkbox.value() == 1 for checkbox in checkboxes): control.configure(state="normal") else: control.configure(state="disabled") app = App("Checkboxes") app.mainloop()This might be even closer to what you want to do. The ConditionAction class is a more generic version of your checkboxes class. Here it is used to set the state of a button based on the value of three checkboxes.
import tkinter as tk import operator as op class Checkbox(tk.Checkbutton): """I add an IntVar to a check button""" var_types = {bool:tk.BooleanVar, int:tk.IntVar, float:tk.DoubleVar} def __init__(self, parent, x, y, onvalue=1, offvalue=0, **kwargs): self.variable = self.var_types.get(type(onvalue), tk.StringVar)(value=offvalue) super().__init__(parent, variable=self.variable, onvalue=onvalue, offvalue=offvalue, **kwargs) self.place(x=x, y=y) def value(self): return self.variable.get() def set_value(self, value): self.variable.set(value) class ConditionAction: """ I call a function based on one or more conditions. User provides functions for True(optional) and False (optional), and multiple conditions. The True function is called if any of the conditions are True, else the False function is called. """ def __init__(self, true_action=None, false_action=None): self.true_action = true_action self.false_action = false_action self.conditions = [] def add_condition(self, condition): self.conditions.append(condition) return self def evaluate(self): for condition in self.conditions: if condition(): if self.true_action is not None: self.true_action() break else: if self.false_action is not None: self.false_action() class App(tk.Tk): def __init__(self, title=None, geometry="250x120", **kwargs): super().__init__(**kwargs) if geometry is not None: self.geometry(geometry) if title is not None: self.wm_title(title) self.checkboxes = [ Checkbox(self,10, 10, text="A"), Checkbox(self,10, 50, text="B"), Checkbox(self,10, 90, text="C") ] self.button = tk.Button(self, text="Push Me") self.button.place(x=100, y=10) action = ConditionAction( true_action = lambda:self.button.config(state="normal"), false_action = lambda:self.button.config(state="disabled")) for cb in self.checkboxes: action.add_condition(lambda x=cb: op.eq(x.value(), 1)) cb.config(command=action.evaluate) action.evaluate() app = App("Checkboxes") app.mainloop()Doing this generically or with a custom function will depend on how often you need to do it. If you have hundreds of similar dependencies it makes sense to write a generic tool. If you only need this once or twice it makes sense to write a function specific to each case.