使用嵌套GridSpec与constrained_layout时Matplotlib Button失效问题求助
嘿,这个问题我之前也碰到过,其实这不是你的操作疏漏,是Matplotlib里constrained_layout和嵌套GridSpec交互时的一个小坑,本质是布局调整时轴对象被替换了,导致Button绑定失效。
为啥会这样?
当你开了constrained_layout=True,Matplotlib会自动帮你调整子图间距,但对于用subgridspec创建的嵌套轴,它在布局过程中会悄悄把原来的轴实例替换成新的——而你创建Button的时候绑定的是旧轴,自然就没法响应悬停和点击了。但直接用顶层GridSpec创建的轴不会被替换,所以之前的代码能正常工作。
怎么解决?
给你两个靠谱的方案,都不用放弃constrained_layout:
方案一:等布局稳定后再创建Button
利用Matplotlib的draw_event,等第一次绘图完成、轴的位置彻底确定后再绑定Button,这样就能拿到最终有效的轴对象:
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec from matplotlib.widgets import Button def on_click(event): print("hey") def create_button_after_layout(event): # 只创建一次,避免重复绑定事件 if not hasattr(fig, 'button_ready'): # 取最后一个创建的轴,就是我们要的gs2[0,1]对应的轴 target_ax = fig.axes[-1] b = Button(target_ax, 'hey') b.on_clicked(on_click) fig.button_ready = True 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") # 嵌套GridSpec创建轴 gs2 = gs[1, 0].subgridspec(1, 2) ax2 = fig.add_subplot(gs2[0, 1]) # 绑定绘图完成事件,延迟创建按钮 fig.canvas.mpl_connect('draw_event', create_button_after_layout) plt.show()
方案二:换用GridSpecFromSubplotSpec创建嵌套布局
官方其实更推荐用GridSpecFromSubplotSpec来做嵌套,这种方式下constrained_layout不会替换轴对象,Button能直接正常工作:
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") # 用GridSpecFromSubplotSpec替代subgridspec gs2 = gridspec.GridSpecFromSubplotSpec(1, 2, subplot_spec=gs[1, 0]) ax2 = fig.add_subplot(gs2[0, 1]) b = Button(ax2, 'hey') b.on_clicked(on_click) plt.show()
这两种方案都能完美解决你的问题,方案二更简洁,适合大多数场景;方案一灵活性更高,要是你有更复杂的嵌套布局也能hold住。
内容的提问来源于stack exchange,提问作者cycleback
相关产品推荐
相关产品推荐

