From 8ea8f69deed0bdf24c74eba74f2942ea32af163f Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Wed, 28 Jan 2026 18:02:42 +0200 Subject: [PATCH 1/2] widgets: test _Buttons' callbacks --- lib/matplotlib/tests/test_widgets.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index 2f6c91b879a7..ea1bdbe27f23 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1219,6 +1219,25 @@ def test_check_button_props(fig_test, fig_ref): cb.set_check_props({**check_props, 's': (24 / 2)**2}) +@pytest.mark.parametrize("widget", [widgets.RadioButtons, widgets.CheckButtons]) +def test__buttons_callbacks(ax, widget): + """Tests what https://github.com/matplotlib/matplotlib/pull/31031 fixed""" + on_clicked = mock.Mock(spec=noop, return_value=None) + button = widget(ax, ["Test Button"]) + button.on_clicked(on_clicked) + MouseEvent._from_ax_coords( + "button_press_event", + ax, + ax.transData.inverted().transform(ax.transAxes.transform( + # (x, y) of the 0th button defined at + # `{Check,Radio}Buttons._init_props` + (0.15, 0.5), + )), + 1, + )._process() + on_clicked.assert_called_once() + + def test_slider_slidermin_slidermax_invalid(): fig, ax = plt.subplots() # test min/max with floats From f701624eaecb9f1525796555430b398a498323e9 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sat, 24 Jan 2026 22:41:48 +0200 Subject: [PATCH 2/2] RadioButtons: fix self._clicked method (followup to #30997) In #30997 the classes `RadioButtons` & `CheckButtons` started sharing more code, as they are fundamentally similar. When copy-pasting the methods that were seemingly identical, the `_clicked` method was copied from the original `CheckButtons` class, and there the `self._frames` object was used instead of `self._buttons`. This caused an error when actually using and clicking on buttons created with `RadioButtons`, as the `RadioButtons._frames` doesn't exist - something that unfortunately the tests did not catch. Both `CheckButtons._frames` and `CheckButtons._buttons` are very similar so even before #30997 the `CheckButtons._clicked` method could have used `self._checks` and not `self._frames`. Hence this change should be harmless. --- lib/matplotlib/widgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index e4b0146c9816..c9c5a79ae3a3 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1110,11 +1110,11 @@ def _clicked(self, event): if self.ignore(event) or event.button != 1 or not self.ax.contains(event)[0]: return idxs = [ # Indices of frames and of texts that contain the event. - *self._frames.contains(event)[1]["ind"], + *self._buttons.contains(event)[1]["ind"], *[i for i, text in enumerate(self.labels) if text.contains(event)[0]]] if idxs: - coords = self._frames.get_offset_transform().transform( - self._frames.get_offsets()) + coords = self._buttons.get_offset_transform().transform( + self._buttons.get_offsets()) self.set_active( # Closest index, only looking in idxs. idxs[(((event.x, event.y) - coords[idxs]) ** 2).sum(-1).argmin()])