Pablo
Pablo

Reputation: 515

Change the color of 2 buttons in case of clicking on one of them

Using this code:

import tkinter as tk

root = tk.Tk()
btn = tk.Button(root,text="click me",activebackground="red")
btn.grid()
root.mainloop()

I know how to change the background color of a button in case it is pressed (however it's temporary and when I pick the mouse click, the color changes to its default color.)

Suppose I have two buttons, one of them is the wrong answer and the other one is the right answer. Is it possible to change the code so that when the user clicks on the wrong button, its background color changes to red and at the same time the background color of the other button changes to green (I want these changes be permanent)

Upvotes: 1

Views: 967

Answers (3)

OysterShucker
OysterShucker

Reputation: 5531

I assume that the button that will turn red or green will change depending on the question. I wrote a simple little question and answer app as an example of how to dynamically change the buttons. The app is ugly (because it is a quick example), but it works. The doc strings and comments in the code explain how I change the buttons dynamically.

#python 3.8+
from tkinter import Tk, Frame, Button, Entry, StringVar


class Questions(Frame):
    def __init__(self, master, questions, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)
        
        self.out = StringVar()
        
        self.correct = 0
        self.current = 0
        self.questions = questions
        
        self.q = Entry(self, width=36, font='calibri 14 bold', textvariable=self.out)
        self.q.grid(row=0, column=0, columnspan=3)
        
        self.def_btn = dict(
            font             = 'calibri 14',
            background       = 'yellow',
            foreground       = 'black',
            activebackground = 'yellow',
        )
        
        '''
        we give command a lambda so we can pass an id to our answer method
        this "id" will be used to perform some simple maths to change the buttons dynamically
        '''
        self.answer_1 = Button(self, command=lambda id=1: self.answer(id), **self.def_btn)
        self.answer_1.grid(row=1, column=0)
        
        self.answer_2 = Button(self, command=lambda id=2: self.answer(id), **self.def_btn)
        self.answer_2.grid(row=1, column=1)
        
        self.next = Button(self, text="next", font='calibri 14', command=self.next_question)
        self.next.grid(row=1, column=2,)
        
        for i in range(3):
            if i < 2:
                self.grid_rowconfigure(i, weight=1)
            self.grid_columnconfigure(i, weight=1)
        
        #kick off the first question
        self.next.invoke()
        
    def init_question(self, q, a1, a2, id):
        self.out.set(q)
        self.answer_1.config(text=a1, **self.def_btn)
        self.answer_2.config(text=a2, **self.def_btn)
        self.correct = id
        self.next['state'] = 'disabled'
        
    def answer(self, id):
        '''
        self.correct can only be 1 or 2 so
        if 1 ~ abs(1-3) is 2
        if 2 ~ abs(2-3) is 1 
        and in that we can change both buttons dynamically
        we target the __dict__ so we can concoct a key for the desired button
        '''
        self.__dict__[f'answer_{self.correct}']['bg'] = 'green'
        self.__dict__[f'answer_{abs(self.correct-3)}']['bg'] = 'red'
        
        self.out.set(f'That is {"in" if id != self.correct else ""}correct!')
        
        self.next['state'] = 'normal'
    
    def next_question(self):
        if len(self.questions) > self.current:
            self.init_question(**self.questions[self.current])
            
        self.current += 1
        

class App(Tk):
    WIDTH  = 400
    HEIGHT = 200

    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        
        Questions(self, [
            #    question,              both answers,          correct answer id
            dict(q='Are you homeless?', a1='true', a2='false', id=1),
            dict(q='Is your name Unghanda Magdebudhu?', a1='true', a2='false', id=1),
            dict(q='Can you spell "CAT"?', a1='true', a2='false', id=2),
        ]).grid(row=0, column=0, sticky='nswe')

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
    

if __name__ == '__main__':
    app = App()
    app.title("My Application")
    app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
    app.minsize(App.WIDTH, App.HEIGHT)
    app.mainloop()

Upvotes: 1

Anshika Singh
Anshika Singh

Reputation: 1044

A button without a callback is pretty useless. It doesn’t do anything when you press the button.

A function or method that is called when the button is pressed is called the command. The callback can be a function, bound method, or any other callable Python object. If this option is not used, nothing will happen when the user presses the button.

You can use the event of the button being clicked and add a configuration/command to the button. This command will tell the program what to do, when the button is clicked.

As I have done below:

import tkinter as tk

def btn_click():
    btn.configure(bg='red')
    btn2.configure(bg='green')

root = tk.Tk()
btn = tk.Button(root, text="click me", command=btn_click)
btn.grid()
btn2 = tk.Button(root, text="click me")
btn2.grid()
root.mainloop()

Hope this was helpful!

Upvotes: 2

David Duran
David Duran

Reputation: 1826

You can use the command to call a function that sets the background color of the two buttons permanently (via configuring bg property).

The following code changes the color of both buttons when the wrong button is pressed:

import tkinter as tk

def change_color(btn1, btn2):
    btn1.configure(bg="green")  
    btn2.configure(bg="red") 

root = tk.Tk()

btn = tk.Button(root,text="correct button")
btn.pack()

btn2 = tk.Button(root,text="wrong button", command=lambda: change_color(btn, btn2))
btn2.pack()

root.mainloop()

Upvotes: 3

Related Questions