Reputation: 515
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
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
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
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