Jung-suk
Jung-suk

Reputation: 172

Highlighting the selected button in tkinter

I am trying to toggle the parameters of my activebackground and activeforeground on my button. However, when trying to change the background color and text font after a button is selected, and resetting these settings back to how they were before, if any another button is clicked and once again the clicked button background color and font doesn't change.

enter image description here

For example in the above screenshot, "Conversation History" is selected so its in grey color with bold font, and all other menu items are in normal font. If I click on "Important", then that "Important" button becomes grey and bold . The code to render the menu is as follows:

import tkinter as tk

root = tk.Tk()

def abc:
  #this part is not running 

def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {'<Enter>': {'state': 'active'},
                '<Leave>': {'state': 'normal'}}

    w = widget(*args, **kwargs)

    for (k, v) in bindings.items():
        w.bind(k, lambda e, kwarg=v: e.widget.config(**kwarg))

    return w


button1 = ResponsiveWidget(
    tk.Button,
    root,
    text='abc',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat',
    )
button1.place(x=0, y=50)

button2 = ResponsiveWidget(
    tk.Button,
    root,
    text='xyz',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat',command=lambda: abc
    )   #abc is not calling
button2.place(x=0, y=80)

root.mainloop()

new code:

import tkinter as tk

root = tk.Tk()

selected_button = None
last_bg = None

def abc():
    print("abc")  #Not executing this part

def change_selected_button(button):
    global selected_button, last_bg
    if selected_button is not None:
        selected_button.config(bg=last_bg)
    selected_button = button
    last_bg = button.cget("bg")
    button.config(bg="orange")

def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {'<Enter>': {'state': 'active'},
                '<Leave>': {'state': 'normal'}}

    w = widget(*args, **kwargs)

    for (k, v) in bindings.items():
        w.bind(k, lambda e, kwarg=v: e.widget.config(**kwarg))

    return w


button1 = ResponsiveWidget(
    tk.Button,
    root,
    text='abc',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat',
    )
button1.place(x=0, y=50)
button1.config(command=lambda button=button1: change_selected_button(button))

button2 = ResponsiveWidget(
    tk.Button,
    root,
    text='xyz',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat',command=abc
    )  
button2.place(x=0, y=80)
button2.config(command=lambda button=button2: change_selected_button(button))



root.mainloop()

Upvotes: 1

Views: 3921

Answers (1)

TheLizzard
TheLizzard

Reputation: 7680

Try this:

import tkinter as tk

def abc():
    print("abc")

def change_selected_button(button):
    abc()
    global selected_button
    if selected_button is not None:
        selected_button.config(bg="white")
    button.config(bg="light blue")
    selected_button = button

root = tk.Tk()
selected_button = None
for i in range(5):
    button = tk.Button(root, text="Click me")
    button.pack()
    button.config(command=lambda button=button: change_selected_button(button))
root.mainloop()

It uses a global variable selected_button that has the blue background. When a new button is pressed the button in selected_button is reset and the new one is put in the variable.

This is how you would implement it in your code:

import tkinter as tk

root = tk.Tk()

selected_button = None
last_bg = None

def abc():
    print("abc")

def change_selected_button(button):
    abc()
    global selected_button, last_bg
    if selected_button is not None:
        selected_button.config(bg=last_bg)
    selected_button = button
    last_bg = button.cget("bg")
    button.config(bg="orange")

def ResponsiveWidget(widget, *args, **kwargs):
    bindings = {'<Enter>': {'state': 'active'},
                '<Leave>': {'state': 'normal'}}

    w = widget(*args, **kwargs)

    for (k, v) in bindings.items():
        w.bind(k, lambda e, kwarg=v: e.widget.config(**kwarg))

    return w


button1 = ResponsiveWidget(
    tk.Button,
    root,
    text='abc',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat',
    )
button1.place(x=0, y=50)
button1.config(command=lambda button=button1: change_selected_button(button))

button2 = ResponsiveWidget(
    tk.Button,
    root,
    text='xyz',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat'
    )   #abc is not calling
button2.place(x=0, y=80)
button2.config(command=lambda button=button2: change_selected_button(button))

button3 = ResponsiveWidget(
    tk.Button,
    root,
    text='test',
    fg='black',
    activebackground='#B7E3F9',
    activeforeground='black',
    highlightthickness=0,
    relief='flat'
    )   #abc is not calling
button3.place(x=0, y=110)
button3.config(command=lambda button=button3: change_selected_button(button))

root.mainloop()

Upvotes: 1

Related Questions