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.