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

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion lib/matplotlib/colorbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
End-users most likely won't need to directly use this module's API.
"""

import functools
import logging

import numpy as np
Expand Down Expand Up @@ -194,6 +195,14 @@ def get_subplotspec(self):
or getattr(self._orig_locator, "get_subplotspec", lambda: None)())


def _remove_cbar_axes(ax, cbar):
"""
Replacement remove method for a colorbar's axes, so that the colorbar is
properly removed.
"""
cbar.remove()


@_docstring.interpd
class Colorbar:
r"""
Expand Down Expand Up @@ -427,6 +436,10 @@ def __init__(
self._extend_cid2 = self.ax.callbacks.connect(
"ylim_changed", self._do_extends)

# Override axes' remove method to properly remove the colorbar
self._ax_remove = self.ax._remove_method
self.ax._remove_method = functools.partial(_remove_cbar_axes, cbar=self)
Comment thread
timhoffm marked this conversation as resolved.
Comment on lines +439 to +441
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Override axes' remove method to properly remove the colorbar
self._ax_remove = self.ax._remove_method
self.ax._remove_method = functools.partial(_remove_cbar_axes, cbar=self)
# Ensure proper cleanup also when `cbar.ax.remove()` is called. We ensure
# this by overriding the Axes' remove method, so that `cbar.ax.remove()`
# actually calls`cbar.remove()`. In turn, we store the original Axes' remove
# method in `_ax_remove`, which `cbar.remove()` will eventually call to
# clean up the Axes itself.
self._ax_remove = self.ax._remove_method
self.ax._remove_method = lambda self_: self.remove()

This warrants a bit more explanation - at least I had some trouble understanding how this works. Also, You can get away with a lambda and don't need an extra _remove_cbar_axes


@property
def long_axis(self):
"""Axis that has decorations (ticks, etc) on it."""
Expand Down Expand Up @@ -1032,7 +1045,7 @@ def remove(self):
if self.ax in a._colorbars:
a._colorbars.remove(self.ax)

self.ax.remove()
self._ax_remove(self.ax)

self.mappable.callbacks.disconnect(self.mappable.colorbar_cid)
self.mappable.colorbar = None
Expand Down
13 changes: 13 additions & 0 deletions lib/matplotlib/tests/test_colorbar.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import platform
from unittest import mock

import numpy as np
import pytest
Expand Down Expand Up @@ -311,6 +312,18 @@ def test_remove_from_figure_cl():
post_position.get_points())


def test_axes_remove():
"""Removing the colorbar's axes should also remove the colorbar"""
fig, ax = plt.subplots()
sc = ax.scatter([1, 2], [3, 4])
cb = fig.colorbar(sc)

with mock.patch.object(cb, 'remove') as mock_cb_remove:
cb.ax.remove()

mock_cb_remove.assert_called()


def test_colorbarbase():
# smoke test from #3805
ax = plt.gca()
Expand Down
Loading