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

Skip to content

Commit b857640

Browse files
committed
Fix AnnotationBbox picking when it moves offscreen.
If it's drawn once, and then moved directly offscreen (via zoom or pan), then the offset of the box would not be updated, meaning it could be accidentally picked. It's not enough to simply update the location of the box, because children might get picked instead, so disable a pick in `contains` if the annotated point is offscreen, similar to `draw`. Fixes #16946.
1 parent 5ecdbde commit b857640

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

lib/matplotlib/offsetbox.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,11 @@ def contains(self, mouseevent):
15231523
inside, info = self._default_contains(mouseevent)
15241524
if inside is not None:
15251525
return inside, info
1526+
1527+
xy_pixel = self._get_position_xy(None)
1528+
if not self._check_xy(None, xy_pixel):
1529+
return False, {}
1530+
15261531
t, tinfo = self.offsetbox.contains(mouseevent)
15271532
#if self.arrow_patch is not None:
15281533
# a, ainfo=self.arrow_patch.contains(event)
@@ -1641,7 +1646,6 @@ def draw(self, renderer):
16411646
return
16421647

16431648
xy_pixel = self._get_position_xy(renderer)
1644-
16451649
if not self._check_xy(renderer, xy_pixel):
16461650
return
16471651

lib/matplotlib/tests/test_offsetbox.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import matplotlib.pyplot as plt
88
import matplotlib.patches as mpatches
99
import matplotlib.lines as mlines
10+
from matplotlib.backend_bases import MouseButton
11+
1012
from matplotlib.offsetbox import (
11-
AnchoredOffsetbox, DrawingArea, _get_packed_offsets)
13+
AnchoredOffsetbox, AnnotationBbox, DrawingArea, OffsetImage, TextArea,
14+
_get_packed_offsets)
1215

1316

1417
@image_comparison(['offsetbox_clipping'], remove_text=True)
@@ -182,3 +185,59 @@ def test_get_packed_offsets_equal(wd_list, total, sep, expected):
182185
def test_get_packed_offsets_equal_total_none_sep_none():
183186
with pytest.raises(ValueError):
184187
_get_packed_offsets([(1, 0)] * 3, total=None, sep=None, mode='equal')
188+
189+
190+
@pytest.mark.parametrize('child_type', ['draw', 'image', 'text'])
191+
@pytest.mark.parametrize('boxcoords',
192+
['axes fraction', 'axes pixels', 'axes points',
193+
'data'])
194+
def test_picking(child_type, boxcoords):
195+
# These all take up approximately the same area.
196+
if child_type == 'draw':
197+
picking_child = DrawingArea(5, 5)
198+
picking_child.add_artist(mpatches.Rectangle((0, 0), 5, 5, linewidth=0))
199+
elif child_type == 'image':
200+
im = np.ones((5, 5))
201+
im[2, 2] = 0
202+
picking_child = OffsetImage(im)
203+
elif child_type == 'text':
204+
picking_child = TextArea('\N{Black Square}', textprops={'fontsize': 5})
205+
else:
206+
assert False, f'Unknown picking child type {child_type}'
207+
208+
fig, ax = plt.subplots()
209+
ab = AnnotationBbox(picking_child, (0.5, 0.5), boxcoords=boxcoords)
210+
ab.set_picker(True)
211+
ax.add_artist(ab)
212+
213+
calls = 0
214+
def on_pick(event):
215+
nonlocal calls
216+
if event.artist == ab:
217+
calls += 1
218+
fig.canvas.mpl_connect('pick_event', on_pick)
219+
220+
# Annotation should be picked by an event occurring at its center.
221+
if boxcoords == 'axes points':
222+
x, y = ax.transAxes.transform_point((0, 0))
223+
x += 0.5 * fig.dpi / 72
224+
y += 0.5 * fig.dpi / 72
225+
elif boxcoords == 'axes pixels':
226+
x, y = ax.transAxes.transform_point((0, 0))
227+
x += 0.5
228+
y += 0.5
229+
else:
230+
x, y = ax.transAxes.transform_point((0.5, 0.5))
231+
fig.canvas.draw()
232+
calls = 0
233+
fig.canvas.button_press_event(x, y, MouseButton.LEFT)
234+
assert calls == 1
235+
236+
# Annotation should *not* be picked by an event at its original center
237+
# point when the limits have changed enough to hide the *xy* point.
238+
ax.set_xlim(-1, 0)
239+
ax.set_ylim(-1, 0)
240+
fig.canvas.draw()
241+
calls = 0
242+
fig.canvas.button_press_event(x, y, MouseButton.LEFT)
243+
assert calls == 0

0 commit comments

Comments
 (0)