2

I have the following code example. When I press the button the color changes. However only after I move the mouse a little. Can I somehow directly call the draw function?

import matplotlib.pyplot as plt
from matplotlib.widgets import Button

def toggle(_):
    button.status ^= True

    color = [0, 1, 0] if button.status else [1, 0, 0]
    button.color = color
    button.hovercolor = color

    # Stuff that doesn't work...
    plt.draw()
    button.canvas.draw()
    plt.gcf().canvas.draw()


button = Button(plt.axes([.1, .1, .8, .8]), 'Press me')
button.status = True
button.on_clicked(toggle)

plt.show() 
magu_
  • 4,766
  • 3
  • 45
  • 79

3 Answers3

2

I am sure that there is an "official" way to do what you want to do, but here is a hack to simulate a mouse motion event which will trigger the redraw. Add button.canvas.motion_notify_event(0,0) at the end of toggle() so that your code looks like this:

import matplotlib.pyplot as plt
from matplotlib.widgets import Button

def toggle(_):
    button.status ^= True

    color = [0, 1, 0] if button.status else [1, 0, 0]
    button.color = color
    button.hovercolor = color

    button.canvas.motion_notify_event(0,0)

button = Button(plt.axes([.1, .1, .8, .8]), 'Press me')
button.status = True
button.on_clicked(toggle)

plt.show() 
Eric Dill
  • 2,166
  • 2
  • 17
  • 15
0

I had the same problem, and the answer by Eric Dill did not work for me. What worked instead was simply doing

canvas.draw_idle()

instead of

canvas.draw()

See here for more information about the difference between the two.

I'm not sure if this works for all backends, but in my case I'm using GTK3Agg.

user3208430
  • 636
  • 1
  • 6
  • 14
0

First of all thanks for the operator "^=". I didn't know that it works for bool type.

To solve your problem do not forget to set facecolor of the plt.axes:

ax = plt.axes([...])
button = Button(ax, ...)
ax.set(facecolor=color)

Now the button will change its color immediately after clicking. You do not have to move the mouse.

The full code is:

import matplotlib.pyplot as plt
from matplotlib.widgets import Button

ax = plt.axes([.1, .1, .8, .8])
button = Button(ax, 'Press me', color='#CCC', hovercolor='#CCC')


def toggle(event):
    button.status ^= True
    color = [0, 1, 0] if button.status else [1, 0, 0]
    button.color = color
    button.hovercolor = color
    ax.set(facecolor=color) # <<< THE TRICK !!!
    plt.draw()
    # button.canvas.draw() # also works
    # plt.gcf().canvas.draw() # also works


button.status = True
button.on_clicked(toggle)
plt.show()

I have Python 3.10.9 with matplotlib 3.7.1.

Good luck!

Alkor
  • 1