Max2603
Max2603

Reputation: 433

Looping through buttons in tkinter

I have written the following code to create 4 buttons and after clicking at a button the background color of this button is changing and when I click at another one the color of this one is now changing and the color of the old one is changing back to default color. It works quite well but the coding is not efficient. I'm thinking of a loop which iterates through all my buttons to set all buttons which are not active to the default color. How can I accomplish this?

from tkinter import *


def update_Button(number):
  if number == 1:
    Button_1["background"] = Button_1["activebackground"] = "lightblue"
    Button_2.configure(background="SystemButtonFace")
    Button_3.configure(background="SystemButtonFace")
    Button_4.configure(background="SystemButtonFace")
  elif number == 2:
    Button_2["background"] = Button_2["activebackground"] = "lightblue"
    Button_1.configure(background="SystemButtonFace")
    Button_3.configure(background="SystemButtonFace")
  elif number == 3:
    Button_3["background"] = Button_3["activebackground"] = "lightblue"
    Button_2.configure(background="SystemButtonFace")
    Button_1.configure(background="SystemButtonFace")
    Button_4.configure(background="SystemButtonFace")
  elif number == 4:
    Button_4["background"] = Button_4["activebackground"] = "lightblue"
    Button_2.configure(background="SystemButtonFace")
    Button_3.configure(background="SystemButtonFace")
    Button_1.configure(background="SystemButtonFace")

  pass


root = Tk()

Button_font = ("Calibri", 20, "bold")
Button_Size = [70, 70]  # width, height
pady = 5
padx = 5

Button_1 = Button(root, text="1", font=Button_font, command=lambda:  update_Button(1))
Button_1.grid(sticky="wens", pady=pady, padx=padx)

Button_2 = Button(root, text="2", font=Button_font, command=lambda: update_Button(2))
Button_2.grid(sticky="wens", pady=pady, padx=padx)

Button_3 = Button(root, text="3", font=Button_font, command=lambda: update_Button(3))
Button_3.grid(sticky="wens", pady=pady, padx=padx)

Button_4 = Button(root, text="4", font=Button_font, command=lambda: update_Button(4))
Button_4.grid(sticky="wens", pady=pady, padx=padx)

root.mainloop()

like suggest from @Mitiku the solution using a list is:

def update_Button(number):
  number = number-1
  buttons = [Button_1, Button_2, Button_3, Button_4]
  buttons[number]["background"] = buttons[number]["activebackground"] = "lightblue"
  for button in buttons:
    if button == buttons[number]:
        pass
    else:
        button.configure(background="SystemButtonFace")
  pass

Upvotes: 1

Views: 2541

Answers (2)

Ethan Field
Ethan Field

Reputation: 4740

The below achieves what you need:

from tkinter import *

class App:
    def __init__(self, root):
        self.root = root
        self.number = 4 #change me to get more buttons
        self.buttons = []
        for i in range(self.number):
            self.buttons.append(Button(self.root, text="Change!", bg="white", command=lambda c=i: self.command(c)))
            self.buttons[i].pack()
    def command(self, var):
        for i in range(self.number):
            self.buttons[i].configure({"bg": "white", "activebackground": "white"})
        self.buttons[var].configure({"bg": "lightblue", "activebackground": "lightblue"})

root = Tk()
App(root)
root.mainloop()

The main interesting mechanic we use here is lambda.

We declare command=lambda c=i: self.command(c) which let's us call the command callback with the value of i at the time of declaration. This means when we call the command we pass through the integer value of the Button widget's position in the list.


On a side note, this can be accomplished much easier with Radiobuttons. See below:

from tkinter import *

class App:
    def __init__(self, root):
        self.root = root
        self.v = IntVar()
        self.number = 4 #change me to get more buttons
        self.buttons = []
        for i in range(self.number):
            self.buttons.append(Radiobutton(self.root, text="Change!", bg="white", activebackground="lightblue", selectcolor="lightblue", variable=self.v, indicatoron=0, value=i))
            self.buttons[i].pack()

root = Tk()
App(root)
root.mainloop()

Upvotes: 1

Mitiku
Mitiku

Reputation: 5412

you can use list.

    def update_Button(number):
        buttons = [Button_1,Button_2,Button_3,Button_4]
        for button in buttons:
            button.configure(background="SystemButtonFace")
        buttons[number-1]["activebackground"] = "lightblue"

Upvotes: 0

Related Questions