-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Description
Bug summary
If I create a figure with a radiobutton widget and then remove the radio widget axes in order to save the figure without the radiobutton box shown it throws an error in fig.savefig
Code for reproduction
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import RadioButtons
# data creation
x = np.arange(0.0, 3.0, 0.01)
y = np.sin(2*np.pi*x)
# plotting data
fig, ax = plt.subplots()
l, = ax.plot(x, y)
plt.subplots_adjust(left = 0.3)
# creating radio buttons
rax = plt.axes([0.05, 0.5, 0.15, 0.30])
radio = RadioButtons(
rax, labels = ['red', 'blue', 'green'], active=2, activecolor='black')
l.set_color(radio.value_selected)
def color(label):
l.set_color(label)
fig.canvas.draw()
radio.on_clicked(color)
plt.show()
# remove radio buttons axes
radio.ax.remove()
fig.tight_layout()
fig.savefig('figure.png')
Actual outcome
Traceback (most recent call last):
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/cbook.py", line 298, in process
func(*args, **kwargs)
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/widgets.py", line 1665, in _clear
if self.ignore(event) or self.canvas.is_saving():
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/widgets.py", line 120, in
canvas = property(lambda self: self.ax.figure.canvas)
AttributeError: 'NoneType' object has no attribute 'canvas'
Traceback (most recent call last):
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/cbook.py", line 298, in process
func(*args, **kwargs)
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/widgets.py", line 1665, in _clear
if self.ignore(event) or self.canvas.is_saving():
File "/nfs/chess/user/rv43/miniforge3/envs/CHAP_tomo/lib/python3.10/site-packages/matplotlib/widgets.py", line 120, in
canvas = property(lambda self: self.ax.figure.canvas)
AttributeError: 'NoneType' object has no attribute 'canvas'
Expected outcome
This example does produce the correct figure (one with a tight layout and no radiobuttons box), since the error that is thrown is caught by matplotlib and only printed as a warning.
Additional information
In matplotlib/widgets.py:
Replacing:
def _clear(self, event):
"""Internal event handler to clear the buttons."""
if self.ignore(event) or self.canvas.is_saving():
return
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
self.ax.draw_artist(self._buttons)
With:
def _clear(self, event):
"""Internal event handler to clear the buttons."""
if self.ax._stale or self.ignore(event) or self.canvas.is_saving():
return
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
self.ax.draw_artist(self._buttons)
Suppresses the issue, but I'm not sure if that is the desired fix or if self.ax._stale has another purpose. I have not tested CheckButtons widgets, but I'm wondering if the same happens there.
It may be wrapped up in self.ignore(event) by setting self.active = False when the radiobuttons get removed, but I don't know if that has other side effects.
Operating system
Scientific Linux 7, AlmaLinux-9
Matplotlib Version
3.9.2, 3.10.3
Matplotlib Backend
qtagg
Python version
3.10.18
Jupyter version
N/A
Installation
conda