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

Skip to content

Commit b9bdcea

Browse files
anntzertimhoffm
authored andcommitted
Fix Annotation.contains. (#12164)
Annotation.contains always calls get_window_extents() without setting the renderer arg, which is thus None (and this is implicitly allowed by the signature of get_window_extents), but get_window_extents calls update_positions which *requires* a non-None renderer (it ultimately calls renderer.points_to_pixels). Instead, reuse the code from Text.get_window_extents() which defaults to the artist-or-figure renderer if the arg is None. Example breaking code: from matplotlib import pyplot as plt ann = plt.annotate( "foo", (.5, .5), arrowprops={"arrowstyle": "->"}, textcoords="offset points", xytext=(10, 10)) plt.gcf().canvas.mpl_connect( "button_press_event", lambda event: print(ann.contains(event))) plt.show() and click anywhere to trigger an AttributeError.
1 parent 1b66c1d commit b9bdcea

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

lib/matplotlib/text.py

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -895,25 +895,26 @@ def get_verticalalignment(self):
895895
return self._verticalalignment
896896

897897
def get_window_extent(self, renderer=None, dpi=None):
898-
'''
899-
Return a `~matplotlib.transforms.Bbox` object bounding
900-
the text, in display units.
898+
"""
899+
Return the `Bbox` bounding the text, in display units.
901900
902-
In addition to being used internally, this is useful for
903-
specifying clickable regions in a png file on a web page.
901+
In addition to being used internally, this is useful for specifying
902+
clickable regions in a png file on a web page.
904903
905-
*renderer* defaults to the _renderer attribute of the text
906-
object. This is not assigned until the first execution of
907-
:meth:`draw`, so you must use this kwarg if you want
908-
to call `.get_window_extent` prior to the first `draw`. For
909-
getting web page regions, it is simpler to call the method after
910-
saving the figure.
911-
912-
*dpi* defaults to self.figure.dpi; the renderer dpi is
913-
irrelevant. For the web application, if figure.dpi is not
914-
the value used when saving the figure, then the value that
915-
was used must be specified as the *dpi* argument.
916-
'''
904+
Parameters
905+
----------
906+
renderer : Renderer, optional
907+
A renderer is needed to compute the bounding box. If the artist
908+
has already been drawn, the renderer is cached; thus, it is only
909+
necessary to pass this argument when calling `get_window_extent`
910+
before the first `draw`. In practice, it is usually easier to
911+
trigger a draw first (e.g. by saving the figure).
912+
913+
dpi : float, optional
914+
The dpi value for computing the bbox, defaults to
915+
``self.figure.dpi`` (*not* the renderer dpi); should be set e.g. if
916+
to match regions with a figure saved with a custom dpi value.
917+
"""
917918
#return _unit_box
918919
if not self.get_visible():
919920
return Bbox.unit()
@@ -2351,29 +2352,36 @@ def draw(self, renderer):
23512352
Text.draw(self, renderer)
23522353

23532354
def get_window_extent(self, renderer=None):
2354-
'''
2355-
Return a :class:`~matplotlib.transforms.Bbox` object bounding
2356-
the text and arrow annotation, in display units.
2355+
"""
2356+
Return the `Bbox` bounding the text and arrow, in display units.
23572357
2358-
*renderer* defaults to the _renderer attribute of the text
2359-
object. This is not assigned until the first execution of
2360-
:meth:`draw`, so you must use this kwarg if you want
2361-
to call :meth:`get_window_extent` prior to the first
2362-
:meth:`draw`. For getting web page regions, it is
2363-
simpler to call the method after saving the figure. The
2364-
*dpi* used defaults to self.figure.dpi; the renderer dpi is
2365-
irrelevant.
2366-
'''
2367-
self.update_positions(renderer)
2358+
Parameters
2359+
----------
2360+
renderer : Renderer, optional
2361+
A renderer is needed to compute the bounding box. If the artist
2362+
has already been drawn, the renderer is cached; thus, it is only
2363+
necessary to pass this argument when calling `get_window_extent`
2364+
before the first `draw`. In practice, it is usually easier to
2365+
trigger a draw first (e.g. by saving the figure).
2366+
"""
2367+
# This block is the same as in Text.get_window_extent, but we need to
2368+
# set the renderer before calling update_positions().
23682369
if not self.get_visible():
23692370
return Bbox.unit()
2371+
if renderer is not None:
2372+
self._renderer = renderer
2373+
if self._renderer is None:
2374+
self._renderer = self.figure._cachedRenderer
2375+
if self._renderer is None:
2376+
raise RuntimeError('Cannot get window extent w/o renderer')
2377+
2378+
self.update_positions(self._renderer)
23702379

2371-
text_bbox = Text.get_window_extent(self, renderer=renderer)
2380+
text_bbox = Text.get_window_extent(self)
23722381
bboxes = [text_bbox]
23732382

23742383
if self.arrow_patch is not None:
2375-
bboxes.append(
2376-
self.arrow_patch.get_window_extent(renderer=renderer))
2384+
bboxes.append(self.arrow_patch.get_window_extent())
23772385

23782386
return Bbox.union(bboxes)
23792387

0 commit comments

Comments
 (0)