Skip to content

Commit

Permalink
Merge pull request #25442 from anntzer/rd
Browse files Browse the repository at this point in the history
Fix disconnection of callbacks when draggable artist is deparented.
  • Loading branch information
ksunden committed Mar 14, 2023
2 parents 3237401 + 3ab8308 commit 370547e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 17 deletions.
31 changes: 14 additions & 17 deletions lib/matplotlib/offsetbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -1500,16 +1500,23 @@ def __init__(self, ref_artist, use_blit=False):
ref_artist.set_picker(True)
self.got_artist = False
self._use_blit = use_blit and self.canvas.supports_blit
self.cids = [
self.canvas.callbacks._connect_picklable(
'pick_event', self.on_pick),
self.canvas.callbacks._connect_picklable(
'button_release_event', self.on_release),
callbacks = ref_artist.figure._canvas_callbacks
self._disconnectors = [
functools.partial(
callbacks.disconnect, callbacks._connect_picklable(name, func))
for name, func in [
("pick_event", self.on_pick),
("button_release_event", self.on_release),
("motion_notify_event", self.on_motion),
]
]

# A property, not an attribute, to maintain picklability.
canvas = property(lambda self: self.ref_artist.figure.canvas)

cids = property(lambda self: [
disconnect.args[0] for disconnect in self._disconnectors[:2]])

def on_motion(self, evt):
if self._check_still_parented() and self.got_artist:
dx = evt.x - self.mouse_x
Expand All @@ -1536,16 +1543,12 @@ def on_pick(self, evt):
self.ref_artist.draw(
self.ref_artist.figure._get_renderer())
self.canvas.blit()
self._c1 = self.canvas.callbacks._connect_picklable(
"motion_notify_event", self.on_motion)
self.save_offset()

def on_release(self, event):
if self._check_still_parented() and self.got_artist:
self.finalize_offset()
self.got_artist = False
self.canvas.mpl_disconnect(self._c1)

if self._use_blit:
self.ref_artist.set_animated(False)

Expand All @@ -1558,14 +1561,8 @@ def _check_still_parented(self):

def disconnect(self):
"""Disconnect the callbacks."""
for cid in self.cids:
self.canvas.mpl_disconnect(cid)
try:
c1 = self._c1
except AttributeError:
pass
else:
self.canvas.mpl_disconnect(c1)
for disconnector in self._disconnectors:
disconnector()

def save_offset(self):
pass
Expand Down
8 changes: 8 additions & 0 deletions lib/matplotlib/tests/test_offsetbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,3 +450,11 @@ def test_paddedbox():
pb = PaddedBox(ta, pad=15, draw_frame=True)
ab = AnchoredOffsetbox('lower right', child=pb)
ax.add_artist(ab)


def test_remove_draggable():
fig, ax = plt.subplots()
an = ax.annotate("foo", (.5, .5))
an.draggable(True)
an.remove()
MouseEvent("button_release_event", fig.canvas, 1, 1)._process()

0 comments on commit 370547e

Please sign in to comment.