Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1ff61cf

Browse files
tacaswellksunden
authored andcommitted
FIX: only try to update blit caches if the canvas we expect
Because we may switch the canvas to a different type (that may not support blitting) when saving, check it `_clear` that the current canvas is the canvas we expect when we update the blitting caches on the draw_event callback. Closes #25075
1 parent 74f4fcb commit 1ff61cf

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

lib/matplotlib/tests/test_widgets.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
import io
23
from unittest import mock
34

45
from matplotlib._api.deprecation import MatplotlibDeprecationWarning
@@ -23,6 +24,45 @@ def ax():
2324
return get_ax()
2425

2526

27+
def test_save_blitted_widget_as_pdf():
28+
from matplotlib.widgets import CheckButtons, RadioButtons
29+
from matplotlib.cbook import _get_running_interactive_framework
30+
if _get_running_interactive_framework() not in ['headless', None]:
31+
pytest.xfail("Callback exceptions are not raised otherwise.")
32+
33+
fig, ax = plt.subplots(
34+
nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2]
35+
)
36+
default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges'])
37+
styled_rb = RadioButtons(
38+
ax[0, 1], ['Apples', 'Oranges'],
39+
label_props={'color': ['red', 'orange'],
40+
'fontsize': [16, 20]},
41+
radio_props={'edgecolor': ['red', 'orange'],
42+
'facecolor': ['mistyrose', 'peachpuff']}
43+
)
44+
45+
default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'],
46+
actives=[True, True])
47+
styled_cb = CheckButtons(
48+
ax[1, 1], ['Apples', 'Oranges'],
49+
actives=[True, True],
50+
label_props={'color': ['red', 'orange'],
51+
'fontsize': [16, 20]},
52+
frame_props={'edgecolor': ['red', 'orange'],
53+
'facecolor': ['mistyrose', 'peachpuff']},
54+
check_props={'color': ['darkred', 'darkorange']}
55+
)
56+
57+
ax[0, 0].set_title('Default')
58+
ax[0, 1].set_title('Stylized')
59+
# force an Agg render
60+
fig.canvas.draw()
61+
# force a pdf save
62+
with io.BytesIO() as result_after:
63+
fig.savefig(result_after, format='pdf')
64+
65+
2666
@pytest.mark.parametrize('kwargs', [
2767
dict(),
2868
dict(useblit=True, button=1),

lib/matplotlib/widgets.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
10881088

10891089
def _clear(self, event):
10901090
"""Internal event handler to clear the buttons."""
1091-
if self.ignore(event):
1091+
if self.ignore(event) or self.canvas is not self.ax.figure.canvas:
10921092
return
10931093
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
10941094
self.ax.draw_artist(self._checks)
@@ -1700,7 +1700,7 @@ def __init__(self, ax, labels, active=0, activecolor=None, *,
17001700

17011701
def _clear(self, event):
17021702
"""Internal event handler to clear the buttons."""
1703-
if self.ignore(event):
1703+
if self.ignore(event) or self.canvas is not self.ax.figure.canvas:
17041704
return
17051705
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
17061706
self.ax.draw_artist(self._buttons)
@@ -1971,7 +1971,7 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False,
19711971

19721972
def clear(self, event):
19731973
"""Internal event handler to clear the cursor."""
1974-
if self.ignore(event):
1974+
if self.ignore(event) or self.canvas is not self.ax.figure.canvas:
19751975
return
19761976
if self.useblit:
19771977
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
@@ -2106,7 +2106,7 @@ def disconnect(self):
21062106

21072107
def clear(self, event):
21082108
"""Clear the cursor."""
2109-
if self.ignore(event):
2109+
if self.ignore(event) or self.canvas is not self.ax.figure.canvas:
21102110
return
21112111
if self.useblit:
21122112
for canvas, info in self._canvas_infos.items():

0 commit comments

Comments
 (0)