Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib Button not working when in nested GridSpec

I'm trying to use constrained_layout together with nested GridSpecs for placement of subplots and buttons. Here is a minimal example:

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

def on_click(event):
    print("hey")

fig = plt.figure(constrained_layout=True)

gs = gridspec.GridSpec(2, 1, height_ratios=[14, 1], figure=fig)

ax1 = fig.add_subplot(gs[0, 0])
ax1.text(0.5, 0.5, "ax1", va="center", ha="center")

ax2 = fig.add_subplot(gs[1, 0])

b = Button(ax2, 'hey')
b.on_clicked(on_click)

plt.show()

This works fine so far, the button changes color when hovering and the callback is executed on click, here is an image of the button working fine when created with axes from top-level GridSpec

image

Now, when I try to nest GridSpecs, i.e.

ax2 = fig.add_subplot(gs[1, 0])

is replaced by

gs2 = gs[1, 0].subgridspec(1, 2)
ax2 = fig.add_subplot(gs2[0, 1])

the layout is as desired,

image

but the button is not working (no color-change on hover, no reaction on click).

Tried plt.sca(ax2), no change. Interestingly, when I take out the constrained_layout=True, the button works.

Is this a bug, or what is going on here? Can someone please shed some light on this?

Please do not suggest using tight_layout() and/or subplots_adjust(). The above is only a minimal example, in real life I have a rather complex figure with many subplots and several buttons. To avoid overlapping labels etc. I need constrained_layout. tight_layout has limitations (e.g. does not consider all elements properly, like figure.suptitle()). constrained_layout together with nested GridSpec seemed to be a good solution, except the problem above.

Thanks for any help!

like image 313
cycleback Avatar asked Sep 11 '25 10:09

cycleback


1 Answers

As a workaround setting the zorder puts the new axes above the "ghost" made by constrained_layout.

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

def on_click(event):
    print("hey")

fig = plt.figure(constrained_layout=True)

gs = gridspec.GridSpec(2, 1, figure=fig)

ax1 = fig.add_subplot(gs[0, 0])
ax1.text(0.5, 0.5, "ax1", va="center", ha="center")

gs2 = gs[1, 0].subgridspec(1, 2)
ax2 = fig.add_subplot(gs2[0, 1])
ax2.set_zorder(10)
b = Button(ax2, 'hey')
b.on_clicked(on_click)

plt.show()
like image 185
Jody Klymak Avatar answered Sep 14 '25 02:09

Jody Klymak