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

Skip to content

Commit bf2d1dc

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

File tree

6 files changed

+408
-68
lines changed

6 files changed

+408
-68
lines changed
Lines 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

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()

lib/matplotlib/tests/test_widgets.py

Lines 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)