Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit bf2d1dc

Browse filesBrowse files
authored
Merge pull request #24838 from QuLogic/button-props
Add styling support to Check and Radio buttons
2 parents 85d7bb3 + 538a7d5 commit bf2d1dc
Copy full SHA for bf2d1dc

File tree

Expand file treeCollapse file tree

6 files changed

+408
-68
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+408
-68
lines changed
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Custom styling of button widgets
2+
--------------------------------
3+
4+
Additional custom styling of button widgets may be achieved via the
5+
*label_props* and *radio_props* arguments to `.RadioButtons`; and the
6+
*label_props*, *frame_props*, and *check_props* arguments to `.CheckButtons`.
7+
8+
.. plot::
9+
10+
from matplotlib.widgets import CheckButtons, RadioButtons
11+
12+
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(5, 2), width_ratios=[1, 2])
13+
default_rb = RadioButtons(ax[0, 0], ['Apples', 'Oranges'])
14+
styled_rb = RadioButtons(ax[0, 1], ['Apples', 'Oranges'],
15+
label_props={'color': ['red', 'orange'],
16+
'fontsize': [16, 20]},
17+
radio_props={'edgecolor': ['red', 'orange'],
18+
'facecolor': ['mistyrose', 'peachpuff']})
19+
20+
default_cb = CheckButtons(ax[1, 0], ['Apples', 'Oranges'],
21+
actives=[True, True])
22+
styled_cb = CheckButtons(ax[1, 1], ['Apples', 'Oranges'],
23+
actives=[True, True],
24+
label_props={'color': ['red', 'orange'],
25+
'fontsize': [16, 20]},
26+
frame_props={'edgecolor': ['red', 'orange'],
27+
'facecolor': ['mistyrose', 'peachpuff']},
28+
check_props={'color': ['darkred', 'darkorange']})
29+
30+
ax[0, 0].set_title('Default')
31+
ax[0, 1].set_title('Stylized')

‎examples/widgets/check_buttons.py

Copy file name to clipboardExpand all lines: examples/widgets/check_buttons.py
+8-4Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@
2020
s2 = np.sin(6*np.pi*t)
2121

2222
fig, ax = plt.subplots()
23-
l0, = ax.plot(t, s0, visible=False, lw=2, color='k', label='2 Hz')
24-
l1, = ax.plot(t, s1, lw=2, color='r', label='4 Hz')
25-
l2, = ax.plot(t, s2, lw=2, color='g', label='6 Hz')
23+
l0, = ax.plot(t, s0, visible=False, lw=2, color='black', label='1 Hz')
24+
l1, = ax.plot(t, s1, lw=2, color='red', label='2 Hz')
25+
l2, = ax.plot(t, s2, lw=2, color='green', label='3 Hz')
2626
fig.subplots_adjust(left=0.2)
2727

2828
lines_by_label = {l.get_label(): l for l in [l0, l1, l2]}
29+
line_colors = [l.get_color() for l in lines_by_label.values()]
2930

3031
# Make checkbuttons with all plotted lines with correct visibility
3132
rax = fig.add_axes([0.05, 0.4, 0.1, 0.15])
3233
check = CheckButtons(
3334
ax=rax,
3435
labels=lines_by_label.keys(),
35-
actives=[l.get_visible() for l in lines_by_label.values()]
36+
actives=[l.get_visible() for l in lines_by_label.values()],
37+
label_props={'color': line_colors},
38+
frame_props={'edgecolor': line_colors},
39+
check_props={'facecolor': line_colors},
3640
)
3741

3842

‎examples/widgets/radio_buttons.py

Copy file name to clipboardExpand all lines: examples/widgets/radio_buttons.py
+14-6Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,31 @@
2525

2626
axcolor = 'lightgoldenrodyellow'
2727
rax = fig.add_axes([0.05, 0.7, 0.15, 0.15], facecolor=axcolor)
28-
radio = RadioButtons(rax, ('2 Hz', '4 Hz', '8 Hz'))
28+
radio = RadioButtons(rax, ('1 Hz', '2 Hz', '4 Hz'),
29+
label_props={'color': 'cmy', 'fontsize': [12, 14, 16]},
30+
radio_props={'s': [16, 32, 64]})
2931

3032

3133
def hzfunc(label):
32-
hzdict = {'2 Hz': s0, '4 Hz': s1, '8 Hz': s2}
34+
hzdict = {'1 Hz': s0, '2 Hz': s1, '4 Hz': s2}
3335
ydata = hzdict[label]
3436
l.set_ydata(ydata)
35-
plt.draw()
37+
fig.canvas.draw()
3638
radio.on_clicked(hzfunc)
3739

3840
rax = fig.add_axes([0.05, 0.4, 0.15, 0.15], facecolor=axcolor)
39-
radio2 = RadioButtons(rax, ('red', 'blue', 'green'))
41+
radio2 = RadioButtons(
42+
rax, ('red', 'blue', 'green'),
43+
label_props={'color': ['red', 'blue', 'green']},
44+
radio_props={
45+
'facecolor': ['red', 'blue', 'green'],
46+
'edgecolor': ['darkred', 'darkblue', 'darkgreen'],
47+
})
4048

4149

4250
def colorfunc(label):
4351
l.set_color(label)
44-
plt.draw()
52+
fig.canvas.draw()
4553
radio2.on_clicked(colorfunc)
4654

4755
rax = fig.add_axes([0.05, 0.1, 0.15, 0.15], facecolor=axcolor)
@@ -50,7 +58,7 @@ def colorfunc(label):
5058

5159
def stylefunc(label):
5260
l.set_linestyle(label)
53-
plt.draw()
61+
fig.canvas.draw()
5462
radio3.on_clicked(stylefunc)
5563

5664
plt.show()
Loading

‎lib/matplotlib/tests/test_widgets.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_widgets.py
+85-10Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -992,21 +992,38 @@ def test_TextBox(ax, toolbar):
992992
@image_comparison(['check_radio_buttons.png'], style='mpl20', remove_text=True)
993993
def test_check_radio_buttons_image():
994994
ax = get_ax()
995-
# Remove this line when this test image is regenerated.
996-
plt.rcParams['text.kerning_factor'] = 6
995+
fig = ax.figure
996+
fig.subplots_adjust(left=0.3)
997997

998-
plt.subplots_adjust(left=0.3)
999-
rax1 = plt.axes([0.05, 0.7, 0.15, 0.15])
1000-
rax2 = plt.axes([0.05, 0.2, 0.15, 0.15])
1001-
rb = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3'))
998+
rax1 = fig.add_axes([0.05, 0.7, 0.2, 0.15])
999+
rb1 = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3'))
10021000
with pytest.warns(DeprecationWarning,
10031001
match='The circles attribute was deprecated'):
1004-
rb.circles # Trigger the old-style elliptic radiobuttons.
1005-
cb = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'),
1006-
(False, True, True))
1002+
rb1.circles # Trigger the old-style elliptic radiobuttons.
1003+
1004+
rax2 = fig.add_axes([0.05, 0.5, 0.2, 0.15])
1005+
cb1 = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'),
1006+
(False, True, True))
10071007
with pytest.warns(DeprecationWarning,
10081008
match='The rectangles attribute was deprecated'):
1009-
cb.rectangles # Trigger old-style Rectangle check boxes
1009+
cb1.rectangles # Trigger old-style Rectangle check boxes
1010+
1011+
rax3 = fig.add_axes([0.05, 0.3, 0.2, 0.15])
1012+
rb3 = widgets.RadioButtons(
1013+
rax3, ('Radio 1', 'Radio 2', 'Radio 3'),
1014+
label_props={'fontsize': [8, 12, 16],
1015+
'color': ['red', 'green', 'blue']},
1016+
radio_props={'edgecolor': ['red', 'green', 'blue'],
1017+
'facecolor': ['mistyrose', 'palegreen', 'lightblue']})
1018+
1019+
rax4 = fig.add_axes([0.05, 0.1, 0.2, 0.15])
1020+
cb4 = widgets.CheckButtons(
1021+
rax4, ('Check 1', 'Check 2', 'Check 3'), (False, True, True),
1022+
label_props={'fontsize': [8, 12, 16],
1023+
'color': ['red', 'green', 'blue']},
1024+
frame_props={'edgecolor': ['red', 'green', 'blue'],
1025+
'facecolor': ['mistyrose', 'palegreen', 'lightblue']},
1026+
check_props={'color': ['red', 'green', 'blue']})
10101027

10111028

10121029
@check_figures_equal(extensions=["png"])
@@ -1019,6 +1036,41 @@ def test_radio_buttons(fig_test, fig_ref):
10191036
ax.text(.25, 1/3, "coffee", transform=ax.transAxes, va="center")
10201037

10211038

1039+
@check_figures_equal(extensions=['png'])
1040+
def test_radio_buttons_props(fig_test, fig_ref):
1041+
label_props = {'color': ['red'], 'fontsize': [24]}
1042+
radio_props = {'facecolor': 'green', 'edgecolor': 'blue', 'linewidth': 2}
1043+
1044+
widgets.RadioButtons(fig_ref.subplots(), ['tea', 'coffee'],
1045+
label_props=label_props, radio_props=radio_props)
1046+
1047+
cb = widgets.RadioButtons(fig_test.subplots(), ['tea', 'coffee'])
1048+
cb.set_label_props(label_props)
1049+
# Setting the label size automatically increases default marker size, so we
1050+
# need to do that here as well.
1051+
cb.set_radio_props({**radio_props, 's': (24 / 2)**2})
1052+
1053+
1054+
def test_radio_button_active_conflict(ax):
1055+
with pytest.warns(UserWarning,
1056+
match=r'Both the \*activecolor\* parameter'):
1057+
rb = widgets.RadioButtons(ax, ['tea', 'coffee'], activecolor='red',
1058+
radio_props={'facecolor': 'green'})
1059+
# *radio_props*' facecolor wins over *activecolor*
1060+
assert mcolors.same_color(rb._buttons.get_facecolor(), ['green', 'none'])
1061+
1062+
1063+
@check_figures_equal(extensions=['png'])
1064+
def test_radio_buttons_activecolor_change(fig_test, fig_ref):
1065+
widgets.RadioButtons(fig_ref.subplots(), ['tea', 'coffee'],
1066+
activecolor='green')
1067+
1068+
# Test property setter.
1069+
cb = widgets.RadioButtons(fig_test.subplots(), ['tea', 'coffee'],
1070+
activecolor='red')
1071+
cb.activecolor = 'green'
1072+
1073+
10221074
@check_figures_equal(extensions=["png"])
10231075
def test_check_buttons(fig_test, fig_ref):
10241076
widgets.CheckButtons(fig_test.subplots(), ["tea", "coffee"], [True, True])
@@ -1031,6 +1083,29 @@ def test_check_buttons(fig_test, fig_ref):
10311083
ax.text(.25, 1/3, "coffee", transform=ax.transAxes, va="center")
10321084

10331085

1086+
@check_figures_equal(extensions=['png'])
1087+
def test_check_button_props(fig_test, fig_ref):
1088+
label_props = {'color': ['red'], 'fontsize': [24]}
1089+
frame_props = {'facecolor': 'green', 'edgecolor': 'blue', 'linewidth': 2}
1090+
check_props = {'facecolor': 'red', 'linewidth': 2}
1091+
1092+
widgets.CheckButtons(fig_ref.subplots(), ['tea', 'coffee'], [True, True],
1093+
label_props=label_props, frame_props=frame_props,
1094+
check_props=check_props)
1095+
1096+
cb = widgets.CheckButtons(fig_test.subplots(), ['tea', 'coffee'],
1097+
[True, True])
1098+
cb.set_label_props(label_props)
1099+
# Setting the label size automatically increases default marker size, so we
1100+
# need to do that here as well.
1101+
cb.set_frame_props({**frame_props, 's': (24 / 2)**2})
1102+
# FIXME: Axes.scatter promotes facecolor to edgecolor on unfilled markers,
1103+
# but Collection.update doesn't do that (it forgot the marker already).
1104+
# This means we cannot pass facecolor to both setters directly.
1105+
check_props['edgecolor'] = check_props.pop('facecolor')
1106+
cb.set_check_props({**check_props, 's': (24 / 2)**2})
1107+
1108+
10341109
@check_figures_equal(extensions=["png"])
10351110
def test_check_buttons_rectangles(fig_test, fig_ref):
10361111
# Test should be removed once .rectangles is removed

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.