With the below code Button-1
click called relief
change works only when it is already clicked once (only double click works 1st time, 2nd time it is ok, but if an other widget is selected, the same happens):
def selected(event):
event.widget.config(relief=SUNKEN if event.widget.cget("relief") == "raised" else RAISED)
B1 = Button(root, text ='BUTTON1', font='-size 8', relief=RAISED)
B1.bind("<Button>", selected)
B1.grid(row = 1, column = 2, sticky = N+E+S+W)
B2 = Button(root, text ='BUTTON2', font='-size 8', relief=RAISED)
B2.bind("<Button>", selected)
B2.grid(row = 2, column = 2, sticky = N+E+S+W)
With Button-2 and Button-3 it is working properly,
What is the reason?
Problem is that tkinter
can bind many functions to event and there is already binded default function which changed relief
when you click button. You can use return "break"
in your function to inform tkinter
that you processed this event and it will skip other functions.
Or you could use standard command=
to assing function and then it will skip other function.
import tkinter as tk # PEP8: `import *` is not preferred
# --- functions ---
def selected1(event):
event.widget.config(relief='sunken' if event.widget.cget('relief') == 'raised' else 'raised')
return "break"
def selected2():
B2.config(relief='sunken' if B2.cget("relief") == 'raised' else 'raised')
# --- main ---
root = tk.Tk()
B1 = tk.Button(root, text='BUTTON1', relief='raised')
B1.bind("<Button>", selected1)
B1.grid(row=1, column=2, sticky='news')
B2 = tk.Button(root, text='BUTTON2', relief='raised', command=selected2)
B2.grid(row=2, column=2, sticky='news')
root.mainloop()
The same using for
-loop and lambda
.
Normally it use only reference to button
which valeu is changed in loop so finally all functions use reference to the same value - which is last value assigned in loop.
Using lambda arg=button
it create new variable in every loop and copy value from button
to arg
so every widget use different arg with differen value.
import tkinter as tk # PEP8: `import *` is not preferred
# --- functions ---
def selected(widget):
widget.config(relief='sunken' if widget.cget('relief') == 'raised' else 'raised')
# --- main ---
root = tk.Tk()
for x in range(1, 6):
button = tk.Button(root, text=f'LOOP BUTTON {x}', relief='raised')
#button.config(command=lambda arg=button:selected3(arg))
button['command'] = lambda arg=button:selected(arg)
button.grid(row=x, column=2, sticky='news')
root.mainloop()
As @acw1668 mentioned in comment you can also uses Checkbutton(..., indicator=False)
to get the same effect without extra function
import tkinter as tk # PEP8: `import *` is not preferred
# --- main ---
root = tk.Tk()
for x in range(1, 6):
button = tk.Checkbutton(root, text=f'LOOP BUTTON {x}', indicator=False, padx=10, pady=5)
button.grid(row=x, column=2, sticky='news')
root.mainloop()
It seems that you just have to tweak a single thing in order to single-click on buttons to activate the function. Try changing the bind to this:
def selected(event):
event.widget.config(relief=SUNKEN if event.widget.cget("relief") == "raised" else RAISED)
B1 = Button(root, text ='BUTTON1', font='-size 8', relief=RAISED)
B1.bind("<Button-1>", selected)
B1.grid(row = 1, column = 2, sticky = N+E+S+W)
B2 = Button(root, text ='BUTTON2', font='-size 8', relief=RAISED)
B2.bind("<Button-1>", selected)
B2.grid(row = 2, column = 2, sticky = N+E+S+W)
Just change "Button" to "Button-1" and please tell me if there are errors
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.