Skip to content

Commit 4c11aad

Browse files
committed
Fix double picks.
pick_events were previously incorrectly emitted twice due to the combination of two recent(ish) chnages: Figures now always start with a FigureCanvasBase attached -- eventually switching to a concrete subclass of FigureCanvasBase for display or saving --, and callbacks are now actually stored at the Figure level rather than the Canvas level. Hence, the button_pick_id callback (in charge of emitting picks) would previously be both registered both through the FigureCanvasBase and the concrete subclass. The fix is to also move that callback to the Figure level, so that each Figure only has one such callback.
1 parent 97258e9 commit 4c11aad

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,15 +1726,13 @@ def __init__(self, figure=None):
17261726
self._button = None # the button pressed
17271727
self._key = None # the key pressed
17281728
self._lastx, self._lasty = None, None
1729-
self.button_pick_id = self.mpl_connect('button_press_event', self.pick)
1730-
self.scroll_pick_id = self.mpl_connect('scroll_event', self.pick)
17311729
self.mouse_grabber = None # the axes currently grabbing mouse
17321730
self.toolbar = None # NavigationToolbar2 will set me
17331731
self._is_idle_drawing = False
17341732

1735-
@property
1736-
def callbacks(self):
1737-
return self.figure._canvas_callbacks
1733+
callbacks = property(lambda self: self.figure._canvas_callbacks)
1734+
button_pick_id = property(lambda self: self.figure._button_pick_id)
1735+
scroll_pick_id = property(lambda self: self.figure._scroll_pick_id)
17381736

17391737
@classmethod
17401738
@functools.lru_cache()

lib/matplotlib/figure.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,10 @@ def __init__(self,
21062106
# a proxy property), but that actually need to be on the figure for
21072107
# pickling.
21082108
self._canvas_callbacks = cbook.CallbackRegistry()
2109+
self._button_pick_id = self._canvas_callbacks.connect(
2110+
'button_press_event', lambda event: self.canvas.pick(event))
2111+
self._scroll_pick_id = self._canvas_callbacks.connect(
2112+
'scroll_event', lambda event: self.canvas.pick(event))
21092113

21102114
if figsize is None:
21112115
figsize = mpl.rcParams['figure.figsize']

lib/matplotlib/tests/test_backend_bases.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ def test_location_event_position(x, y):
120120
assert re.match("x=foo +y=foo", ax.format_coord(x, y))
121121

122122

123+
def test_pick():
124+
fig = plt.figure()
125+
fig.text(.5, .5, "hello", ha="center", va="center", picker=True)
126+
fig.canvas.draw()
127+
picks = []
128+
fig.canvas.mpl_connect("pick_event", lambda event: picks.append(event))
129+
start_event = MouseEvent(
130+
"button_press_event", fig.canvas, *fig.transFigure.transform((.5, .5)),
131+
MouseButton.LEFT)
132+
fig.canvas.callbacks.process(start_event.name, start_event)
133+
assert len(picks) == 1
134+
135+
123136
def test_interactive_zoom():
124137
fig, ax = plt.subplots()
125138
ax.set(xscale="logit")

0 commit comments

Comments
 (0)