20

Is there a possibility to change the background-color of a Button after hovering on it? What is the code for this in Tkinter?

martineau
  • 119,623
  • 25
  • 170
  • 301
Stavrius Mtvs
  • 231
  • 2
  • 4
  • 7
  • 2
    After hovering over it or *while* hovering over it? Are you using ttk? Please show us a [mcve] of your code. – Novel Apr 17 '18 at 22:53
  • 2
    `Button`s have options you can pass when constructing one that control their color when the cursor is over them called `activebackground` and `activeforeground`, try setting and using those. Here's some [documentation](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/button.html). – martineau Apr 17 '18 at 23:27

2 Answers2

37

Sadly the activebackground and activeforeground options only seem to work when you are clicking on the button rather than when you hover over the button. Use the <Leave> and <Enter> events instead

import tkinter as tk

def on_enter(e):
    myButton['background'] = 'green'

def on_leave(e):
    myButton['background'] = 'SystemButtonFace'

root = tk.Tk()
myButton = tk.Button(root,text="Click Me")
myButton.grid()


myButton.bind("<Enter>", on_enter)
myButton.bind("<Leave>", on_leave)

root.mainloop()

As pointed out in the comments, if we want multiple buttons, we can bind the buttons to functions that use the event data for the click event to change the background of the button.

import tkinter as tk

def on_enter(e):
    e.widget['background'] = 'green'

def on_leave(e):
    e.widget['background'] = 'SystemButtonFace'

root = tk.Tk()
myButton = tk.Button(root,text="Click Me")
myButton.grid()


myButton.bind("<Enter>", on_enter)
myButton.bind("<Leave>", on_leave)

myButton2 = tk.Button(root,text="Click Me")
myButton2.grid()


myButton2.bind("<Enter>", on_enter)
myButton2.bind("<Leave>", on_leave)

root.mainloop()

A slicker way to do it for multiple buttons would be to create a new Button class that modifies the behaviour of the default button so that the activebackground actually works when you hover.

import tkinter as tk

class HoverButton(tk.Button):
    def __init__(self, master, **kw):
        tk.Button.__init__(self,master=master,**kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        self['background'] = self['activebackground']

    def on_leave(self, e):
        self['background'] = self.defaultBackground

root = tk.Tk()

classButton = HoverButton(root,text="Classy Button", activebackground='green')
classButton.grid()

root.mainloop()
scotty3785
  • 6,763
  • 1
  • 25
  • 35
  • 1
    What if I want to change the image in the button when I hover over it? – Raj Mehta Nov 02 '18 at 18:52
  • 7
    @RajMehta Ask a new question. – scotty3785 Nov 05 '18 at 08:26
  • 3
    A simpler way to handle multiple `Button`s that does require defining a subclass would be by making the bound functions get the widget from the event argument they are passed — i.e. in function `on_enter():` use `e.widget.config(background='green'))` instead of `myButton['background'] = 'green'`. – martineau Dec 20 '20 at 21:51
  • @martineau I've updated the answer to include this option too. – scotty3785 Jan 07 '21 at 14:10
  • 1
    scotty3785: Yep, that's how to make the callbacks reusable, as I suggested — so now your answer's even more comprehensive. `;¬)` – martineau Jan 07 '21 at 15:17
  • This is such a great solution. @RajMehta, I believe that you could just use the `on_enter` and `on_leave` functions, with code to change the image inside the method. – SamTheProgrammer Jan 27 '22 at 17:05
7

Plain and simple

Context: Unix based computers, might not work for Windows nor MACOSX

In your Button object properties you have the tags: activebackground & activeforeground that are activated whenever there is interaction with the instace created. That is: the button object you've created.

e.g.

from tkinter import *

root = Tk()

button = Button(root, text="Click me", bg="#000", fg="#fff", activebackground="#f00", activeforeground="#fff")
button.pack()

root.mainloop()
victorkolis
  • 780
  • 13
  • 13
  • 2
    I almost skipped trying this answer because of the comments above and the fact that it had no votes. This should be the accepted answer. It works perfectly on mouseover for me on Linux python3. – mp035 Nov 24 '21 at 03:18
  • 1
    One thing that must be brought to heed's the fact that, there is the Button and the ttk.Button objects. See the solution for the ttk.Button object -> https://stackoverflow.com/questions/27347981/how-to-change-the-color-of-ttk-button/65729636#65729636 – victorkolis Nov 26 '21 at 12:16
  • I think it has been upvoted less due to the fact that it doesn't seem to work for hovering within Windows 10, where many GUI apps are distributed. – SamTheProgrammer Jan 27 '22 at 17:07