You
- could use 2 for loops for the row and col.
- could apply all the
BoolImage
parameters in the init
- don't really need to use partial, the event has a pointer to the widget that triggered the event.
- don't need the if statement in the event handler to find the current state to then choose what to change it to, just use the toggle_state method.
#! /usr/bin/env python3 import tkinter as tk class BoolImage(tk.Label): def __init__(self, false_img_path, true_img_path, *args, **kwargs): super().__init__(*args, **kwargs) self._state = False self._images = {False: false_img_path, True: true_img_path} self._set_image() def _set_image(self): self.photo_image = tk.PhotoImage(file=self._images[self.state]) self.config(image=self.photo_image) def toggle_state(self): self.state = not self.state @property def state(self): return self._state @state.setter def state(self, state): self._state = state self._set_image() class Window: def __init__(self, parent): self.parent = parent self.btns = [] for row in range(3): btns_row = [] for col in range(5): btn = BoolImage( "../images/buttons/off.png", "../images/buttons/on.png", parent, cursor="hand2", text=f"Button {row}:{col}", compound="bottom", font=("system", 12, "bold"), ) btn.grid(column=col, row=row, sticky="news") btn.bind("<Button-1>", self.switch) btns_row.append(btn) self.btns.append(btns_row) def switch(self, event): event.widget.toggle_state() def main(): root = tk.Tk() root.config(padx=8, pady=4) Window(root) root.mainloop() if __name__ == "__main__": main()