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

Skip to content

Commit 4ca5e0c

Browse files
committed
*Buttons: use a shared _Buttons class
Share all the trivial functions which are identical without any further modifications.
1 parent d2814cf commit 4ca5e0c

2 files changed

Lines changed: 80 additions & 128 deletions

File tree

doc/api/widgets_api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Widget classes
2727
Cursor
2828
MultiCursor
2929
Button
30+
_Buttons
3031
CheckButtons
3132
RadioButtons
3233
SliderBase

lib/matplotlib/widgets.py

Lines changed: 79 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,84 @@ def _expand_text_props(props):
10371037
return cycler(**props)() if props else itertools.repeat({})
10381038

10391039

1040-
class CheckButtons(AxesWidget):
1040+
class _Buttons(AxesWidget):
1041+
"""
1042+
The base class for `CheckButtons` and `RadioButtons`.
1043+
1044+
This class provides common functionality for button widgets,
1045+
such as handling click events, managing button labels, and connecting callbacks.
1046+
1047+
The class itself is private and may be changed or removed without prior warning.
1048+
However, the public API it provides to subclasses is stable and considered
1049+
public on the subclasses.
1050+
"""
1051+
1052+
def _clear(self, event):
1053+
"""Internal event handler to clear the buttons."""
1054+
if self.ignore(event) or self.canvas.is_saving():
1055+
return
1056+
if self._useblit and self.canvas.supports_blit:
1057+
self._save_blit_background(self.canvas.copy_from_bbox(self.ax.bbox))
1058+
self.ax.draw_artist(self._buttons)
1059+
1060+
def set_label_props(self, props):
1061+
"""
1062+
Set properties of the `.Text` labels.
1063+
1064+
.. versionadded:: 3.7
1065+
1066+
Parameters
1067+
----------
1068+
props : dict
1069+
Dictionary of `.Text` properties to be used for the labels. Same
1070+
format as label_props argument of :class:`RadioButtons` or
1071+
:class:`CheckButtons`.
1072+
"""
1073+
_api.check_isinstance(dict, props=props)
1074+
props = _expand_text_props(props)
1075+
for text, prop in zip(self.labels, props):
1076+
text.update(prop)
1077+
1078+
@_call_with_reparented_event
1079+
def _clicked(self, event):
1080+
if self.ignore(event) or event.button != 1 or not self.ax.contains(event)[0]:
1081+
return
1082+
idxs = [ # Indices of frames and of texts that contain the event.
1083+
*self._frames.contains(event)[1]["ind"],
1084+
*[i for i, text in enumerate(self.labels) if text.contains(event)[0]]]
1085+
if idxs:
1086+
coords = self._frames.get_offset_transform().transform(
1087+
self._frames.get_offsets())
1088+
self.set_active( # Closest index, only looking in idxs.
1089+
idxs[(((event.x, event.y) - coords[idxs]) ** 2).sum(-1).argmin()])
1090+
1091+
def on_clicked(self, func):
1092+
"""
1093+
Connect the callback function *func* to button click events.
1094+
1095+
Parameters
1096+
----------
1097+
func : callable
1098+
When the button is clicked, call *func* with button label.
1099+
When all buttons are cleared, call *func* with None.
1100+
The callback func must have the signature::
1101+
1102+
def func(label: str | None) -> Any
1103+
1104+
Return values may exist, but are ignored.
1105+
1106+
Returns
1107+
-------
1108+
A connection id, which can be used to disconnect the callback.
1109+
"""
1110+
return self._observers.connect('clicked', func)
1111+
1112+
def disconnect(self, cid):
1113+
"""Remove the observer with connection id *cid*."""
1114+
self._observers.disconnect(cid)
1115+
1116+
1117+
class CheckButtons(_Buttons):
10411118
r"""
10421119
A GUI neutral set of check buttons.
10431120
@@ -1152,44 +1229,6 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
11521229

11531230
self._observers = cbook.CallbackRegistry(signals=["clicked"])
11541231

1155-
def _clear(self, event):
1156-
"""Internal event handler to clear the buttons."""
1157-
if self.ignore(event) or self.canvas.is_saving():
1158-
return
1159-
if self._useblit and self.canvas.supports_blit:
1160-
self._save_blit_background(self.canvas.copy_from_bbox(self.ax.bbox))
1161-
self.ax.draw_artist(self._buttons)
1162-
1163-
@_call_with_reparented_event
1164-
def _clicked(self, event):
1165-
if self.ignore(event) or event.button != 1 or not self.ax.contains(event)[0]:
1166-
return
1167-
idxs = [ # Indices of frames and of texts that contain the event.
1168-
*self._frames.contains(event)[1]["ind"],
1169-
*[i for i, text in enumerate(self.labels) if text.contains(event)[0]]]
1170-
if idxs:
1171-
coords = self._frames.get_offset_transform().transform(
1172-
self._frames.get_offsets())
1173-
self.set_active( # Closest index, only looking in idxs.
1174-
idxs[(((event.x, event.y) - coords[idxs]) ** 2).sum(-1).argmin()])
1175-
1176-
def set_label_props(self, props):
1177-
"""
1178-
Set properties of the `.Text` labels.
1179-
1180-
.. versionadded:: 3.7
1181-
1182-
Parameters
1183-
----------
1184-
props : dict
1185-
Dictionary of `.Text` properties to be used for the labels. Same
1186-
format as label_props argument of :class:`CheckButtons`.
1187-
"""
1188-
_api.check_isinstance(dict, props=props)
1189-
props = _expand_text_props(props)
1190-
for text, prop in zip(self.labels, props):
1191-
text.update(prop)
1192-
11931232
def set_frame_props(self, props):
11941233
"""
11951234
Set properties of the check button frames.
@@ -1321,31 +1360,6 @@ def get_checked_labels(self):
13211360
zip(self.labels, self.get_status())
13221361
if box_checked]
13231362

1324-
def on_clicked(self, func):
1325-
"""
1326-
Connect the callback function *func* to button click events.
1327-
1328-
Parameters
1329-
----------
1330-
func : callable
1331-
When the button is clicked, call *func* with button label.
1332-
When all buttons are cleared, call *func* with None.
1333-
The callback func must have the signature::
1334-
1335-
def func(label: str | None) -> Any
1336-
1337-
Return values may exist, but are ignored.
1338-
1339-
Returns
1340-
-------
1341-
A connection id, which can be used to disconnect the callback.
1342-
"""
1343-
return self._observers.connect('clicked', lambda text: func(text))
1344-
1345-
def disconnect(self, cid):
1346-
"""Remove the observer with connection id *cid*."""
1347-
self._observers.disconnect(cid)
1348-
13491363

13501364
class TextBox(AxesWidget):
13511365
"""
@@ -1612,7 +1626,7 @@ def disconnect(self, cid):
16121626
self._observers.disconnect(cid)
16131627

16141628

1615-
class RadioButtons(AxesWidget):
1629+
class RadioButtons(_Buttons):
16161630
"""
16171631
A GUI neutral radio button.
16181632
@@ -1745,44 +1759,6 @@ def __init__(self, ax, labels, active=0, activecolor=None, *,
17451759

17461760
self._observers = cbook.CallbackRegistry(signals=["clicked"])
17471761

1748-
def _clear(self, event):
1749-
"""Internal event handler to clear the buttons."""
1750-
if self.ignore(event) or self.canvas.is_saving():
1751-
return
1752-
if self._useblit and self.canvas.supports_blit:
1753-
self._save_blit_background(self.canvas.copy_from_bbox(self.ax.bbox))
1754-
self.ax.draw_artist(self._buttons)
1755-
1756-
@_call_with_reparented_event
1757-
def _clicked(self, event):
1758-
if self.ignore(event) or event.button != 1 or not self.ax.contains(event)[0]:
1759-
return
1760-
idxs = [ # Indices of buttons and of texts that contain the event.
1761-
*self._buttons.contains(event)[1]["ind"],
1762-
*[i for i, text in enumerate(self.labels) if text.contains(event)[0]]]
1763-
if idxs:
1764-
coords = self._buttons.get_offset_transform().transform(
1765-
self._buttons.get_offsets())
1766-
self.set_active( # Closest index, only looking in idxs.
1767-
idxs[(((event.x, event.y) - coords[idxs]) ** 2).sum(-1).argmin()])
1768-
1769-
def set_label_props(self, props):
1770-
"""
1771-
Set properties of the `.Text` labels.
1772-
1773-
.. versionadded:: 3.7
1774-
1775-
Parameters
1776-
----------
1777-
props : dict
1778-
Dictionary of `.Text` properties to be used for the labels. Same
1779-
format as label_props argument of :class:`RadioButtons`.
1780-
"""
1781-
_api.check_isinstance(dict, props=props)
1782-
props = _expand_text_props(props)
1783-
for text, prop in zip(self.labels, props):
1784-
text.update(prop)
1785-
17861762
def set_radio_props(self, props):
17871763
"""
17881764
Set properties of the `.Text` labels.
@@ -1859,31 +1835,6 @@ def clear(self):
18591835
"""Reset the active button to the initially active one."""
18601836
self.set_active(self._initial_active)
18611837

1862-
def on_clicked(self, func):
1863-
"""
1864-
Connect the callback function *func* to button click events.
1865-
1866-
Parameters
1867-
----------
1868-
func : callable
1869-
When the button is clicked, call *func* with button label.
1870-
When all buttons are cleared, call *func* with None.
1871-
The callback func must have the signature::
1872-
1873-
def func(label: str | None) -> Any
1874-
1875-
Return values may exist, but are ignored.
1876-
1877-
Returns
1878-
-------
1879-
A connection id, which can be used to disconnect the callback.
1880-
"""
1881-
return self._observers.connect('clicked', func)
1882-
1883-
def disconnect(self, cid):
1884-
"""Remove the observer with connection id *cid*."""
1885-
self._observers.disconnect(cid)
1886-
18871838

18881839
class SubplotTool(Widget):
18891840
"""

0 commit comments

Comments
 (0)