Skip to content

Commit 1a31f4f

Browse files
committed
Add styling support to Check and Radio buttons
1 parent 2403d74 commit 1a31f4f

File tree

5 files changed

+311
-65
lines changed

5 files changed

+311
-65
lines changed

examples/widgets/check_buttons.py

Lines 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

Lines 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()
9.52 KB
Loading

lib/matplotlib/tests/test_widgets.py

Lines changed: 65 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,21 @@ 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+
10221054
@check_figures_equal(extensions=["png"])
10231055
def test_check_buttons(fig_test, fig_ref):
10241056
widgets.CheckButtons(fig_test.subplots(), ["tea", "coffee"], [True, True])
@@ -1031,6 +1063,29 @@ def test_check_buttons(fig_test, fig_ref):
10311063
ax.text(.25, 1/3, "coffee", transform=ax.transAxes, va="center")
10321064

10331065

1066+
@check_figures_equal(extensions=['png'])
1067+
def test_check_button_props(fig_test, fig_ref):
1068+
label_props = {'color': ['red'], 'fontsize': [24]}
1069+
frame_props = {'facecolor': 'green', 'edgecolor': 'blue', 'linewidth': 2}
1070+
check_props = {'facecolor': 'red', 'linewidth': 2}
1071+
1072+
widgets.CheckButtons(fig_ref.subplots(), ['tea', 'coffee'], [True, True],
1073+
label_props=label_props, frame_props=frame_props,
1074+
check_props=check_props)
1075+
1076+
cb = widgets.CheckButtons(fig_test.subplots(), ['tea', 'coffee'],
1077+
[True, True])
1078+
cb.set_label_props(label_props)
1079+
# Setting the label size automatically increases default marker size, so we
1080+
# need to do that here as well.
1081+
cb.set_frame_props({**frame_props, 's': (24 / 2)**2})
1082+
# FIXME: Axes.scatter promotes facecolor to edgecolor on unfilled markers,
1083+
# but Collection.update doesn't do that (it forgot the marker already).
1084+
# This means we cannot pass facecolor to both setters directly.
1085+
check_props['edgecolor'] = check_props.pop('facecolor')
1086+
cb.set_check_props({**check_props, 's': (24 / 2)**2})
1087+
1088+
10341089
@check_figures_equal(extensions=["png"])
10351090
def test_check_buttons_rectangles(fig_test, fig_ref):
10361091
# Test should be removed once .rectangles is removed

0 commit comments

Comments
 (0)