Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Add support for horizontal CheckButtons#27946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
QuLogic wants to merge2 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromQuLogic:horizontal-checkbuttons
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletionsdoc/users/next_whats_new/widget_horizontal.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
CheckButtons / RadioButtons widget may now be laid out horizontally
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The `.CheckButtons` and `.RadioButtons` widget's primary layout direction may
now be specified with the *layout_direction* keyword argument:

.. plot::
:include-source:

import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons, RadioButtons

fig = plt.figure(figsize=(4, 2))

# Default orientation is vertical:
rbv = RadioButtons(fig.add_axes((0.05, 0.6, 0.2, 0.35)),
('Radio 1', 'Radio 2', 'Radio 3'),
layout_direction='vertical')
cbv = CheckButtons(fig.add_axes((0.05, 0.2, 0.2, 0.35)),
('Check 1', 'Check 2', 'Check 3'),
layout_direction='vertical')

# Alternatively, a horizontal orientation may be used:
rbh = RadioButtons(fig.add_axes((0.3, 0.6, 0.6, 0.35)),
('Radio 1', 'Radio 2', 'Radio 3'),
layout_direction='horizontal')
cbh = CheckButtons(fig.add_axes((0.3, 0.2, 0.6, 0.35)),
('Check 1', 'Check 2', 'Check 3'),
layout_direction='horizontal')
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 45 additions & 15 deletionslib/matplotlib/tests/test_widgets.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1042,9 +1042,11 @@ def test_lasso_set_props(ax):
assert line.get_alpha() == 0.3


def test_CheckButtons(ax):
@pytest.mark.parametrize('layout_direction', ['vertical', 'horizontal'])
def test_CheckButtons(ax, layout_direction):
labels = ('a', 'b', 'c')
check = widgets.CheckButtons(ax, labels, (True, False, True))
check = widgets.CheckButtons(ax, labels, (True, False, True),
layout_direction=layout_direction)
assert check.get_status() == [True, False, True]
check.set_active(0)
assert check.get_status() == [False, False, True]
Expand DownExpand Up@@ -1097,8 +1099,10 @@ def test_TextBox(ax, toolbar):
assert text_change_event.call_count == 3


def test_RadioButtons(ax):
radio = widgets.RadioButtons(ax, ('Radio 1', 'Radio 2', 'Radio 3'))
@pytest.mark.parametrize('layout_direction', ['vertical', 'horizontal'])
def test_RadioButtons(ax, layout_direction):
radio = widgets.RadioButtons(ax, ('Radio 1', 'Radio 2', 'Radio 3'),
layout_direction=layout_direction)
radio.set_active(1)
assert radio.value_selected == 'Radio 2'
assert radio.index_selected == 1
Expand All@@ -1109,28 +1113,54 @@ def test_RadioButtons(ax):

@image_comparison(['check_radio_buttons.png'], style='mpl20', remove_text=True)
def test_check_radio_buttons_image():
ax = get_ax()
fig = ax.figure
fig.subplots_adjust(left=0.3)
fig = plt.figure()

rb1 = widgets.RadioButtons(fig.add_axes((0.05, 0.7, 0.2, 0.15)),
('Radio 1', 'Radio 2', 'Radio 3'))

rax1 = fig.add_axes((0.05, 0.7, 0.2, 0.15))
rb1 = widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3'))
rb2 = widgets.RadioButtons(fig.add_axes((0.3, 0.7, 0.6, 0.15)),
('Radio 1', 'Radio 2', 'Radio 3'),
layout_direction='horizontal')

rax2 = fig.add_axes((0.05, 0.5, 0.2, 0.15))
cb1 = widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'),
cb1 =widgets.CheckButtons(fig.add_axes((0.05, 0.5, 0.2, 0.15)),
('Check 1', 'Check 2', 'Check 3'),
(False, True, True))

rax3 = fig.add_axes((0.05, 0.3, 0.2, 0.15))
cb2 = widgets.CheckButtons(fig.add_axes((0.3, 0.5, 0.6, 0.15)),
('Check 1', 'Check 2', 'Check 3'),
(False, True, True),
layout_direction='horizontal')

rb3 = widgets.RadioButtons(
rax3, ('Radio 1', 'Radio 2', 'Radio 3'),
fig.add_axes((0.05, 0.3, 0.2, 0.15)),
('Radio 1', 'Radio 2', 'Radio 3'),
label_props={'fontsize': [8, 12, 16],
'color': ['red', 'green', 'blue']},
radio_props={'edgecolor': ['red', 'green', 'blue'],
'facecolor': ['mistyrose', 'palegreen', 'lightblue']})

rb4 = widgets.RadioButtons(
fig.add_axes((0.3, 0.3, 0.6, 0.15)),
('Radio 1', 'Radio 2', 'Radio 3'),
layout_direction='horizontal',
label_props={'fontsize': [8, 12, 16],
'color': ['red', 'green', 'blue']},
radio_props={'edgecolor': ['red', 'green', 'blue'],
'facecolor': ['mistyrose', 'palegreen', 'lightblue']})

rax4 = fig.add_axes((0.05, 0.1, 0.2, 0.15))
cb3 = widgets.CheckButtons(
fig.add_axes((0.05, 0.1, 0.2, 0.15)),
('Check 1', 'Check 2', 'Check 3'), (False, True, True),
label_props={'fontsize': [8, 12, 16],
'color': ['red', 'green', 'blue']},
frame_props={'edgecolor': ['red', 'green', 'blue'],
'facecolor': ['mistyrose', 'palegreen', 'lightblue']},
check_props={'color': ['red', 'green', 'blue']})

cb4 = widgets.CheckButtons(
rax4, ('Check 1', 'Check 2', 'Check 3'), (False, True, True),
fig.add_axes((0.3, 0.1, 0.6, 0.15)),
('Check 1', 'Check 2', 'Check 3'), (False, True, True),
layout_direction='horizontal',
label_props={'fontsize': [8, 12, 16],
'color': ['red', 'green', 'blue']},
frame_props={'edgecolor': ['red', 'green', 'blue'],
Expand Down
72 changes: 59 additions & 13 deletionslib/matplotlib/widgets.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -991,7 +991,8 @@ class CheckButtons(AxesWidget):
"""

def __init__(self, ax, labels, actives=None, *, useblit=True,
label_props=None, frame_props=None, check_props=None):
label_props=None, frame_props=None, check_props=None,
layout_direction='vertical'):
"""
Add check buttons to `~.axes.Axes` instance *ax*.

Expand DownExpand Up@@ -1026,9 +1027,16 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
black color, and 1.0 linewidth.

.. versionadded:: 3.7
layout_direction : {'vertical', 'horizontal'}
The orientation of the buttons: 'vertical' places buttons from top
to bottom, 'horizontal' places buttons from left to right.

.. versionadded:: 3.10
"""
super().__init__(ax)

_api.check_in_list(['vertical', 'horizontal'],
layout_direction=layout_direction)
_api.check_isinstance((dict, None), label_props=label_props,
frame_props=frame_props, check_props=check_props)

Expand All@@ -1042,14 +1050,29 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
self._useblit = useblit and self.canvas.supports_blit
self._background = None

ys = np.linspace(1, 0, len(labels)+2)[1:-1]
if layout_direction == 'vertical':
# Place buttons from top to bottom with buttons at (0.15, y) and labels
# at (0.25, y), where y is evenly spaced within the Axes.
button_ys = label_ys = np.linspace(1, 0, len(labels) + 2)[1:-1]
button_xs = np.full_like(button_ys, 0.15)
label_xs = np.full_like(label_ys, 0.25)
label_ha = 'left'
label_va = 'center'
else:
# Place buttons from left to right with buttons at (x, 0.15) and labels
# at (x, 0.25), where x is evenly spaced within the Axes.
button_xs = label_xs = np.linspace(0, 1, len(labels) + 2)[1:-1]
button_ys = np.full_like(button_xs, 0.15)
label_ys = np.full_like(label_xs, 0.25)
label_ha = 'center'
label_va = 'bottom'

label_props = _expand_text_props(label_props)
self.labels = [
ax.text(0.25, y, label, transform=ax.transAxes,
horizontalalignment="left", verticalalignment="center",
ax.text(x, y, label, transform=ax.transAxes,
horizontalalignment=label_ha, verticalalignment=label_va,
**props)
for y, label, props in zip(ys, labels, label_props)]
forx,y, label, props in zip(label_xs, label_ys, labels, label_props)]
text_size = np.array([text.get_fontsize() for text in self.labels]) / 2

frame_props = {
Expand All@@ -1061,7 +1084,7 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
}
frame_props.setdefault('facecolor', frame_props.get('color', 'none'))
frame_props.setdefault('edgecolor', frame_props.pop('color', 'black'))
self._frames = ax.scatter([0.15] * len(ys), ys, **frame_props)
self._frames = ax.scatter(button_xs, button_ys, **frame_props)
check_props = {
'linewidth': 1,
's': text_size**2,
Expand All@@ -1071,7 +1094,7 @@ def __init__(self, ax, labels, actives=None, *, useblit=True,
'animated': self._useblit,
}
check_props.setdefault('facecolor', check_props.pop('color', 'black'))
self._checks = ax.scatter([0.15] * len(ys), ys, **check_props)
self._checks = ax.scatter(button_xs, button_ys, **check_props)
# The user may have passed custom colours in check_props, so we need to
# create the checks (above), and modify the visibility after getting
# whatever the user set.
Expand DownExpand Up@@ -1557,7 +1580,8 @@ class RadioButtons(AxesWidget):
"""

def __init__(self, ax, labels, active=0, activecolor=None, *,
useblit=True, label_props=None, radio_props=None):
useblit=True, label_props=None, radio_props=None,
layout_direction='vertical'):
"""
Add radio buttons to an `~.axes.Axes`.

Expand DownExpand Up@@ -1593,9 +1617,16 @@ def __init__(self, ax, labels, active=0, activecolor=None, *,
button.

.. versionadded:: 3.7
layout_direction : {'vertical', 'horizontal'}
The orientation of the buttons: 'vertical' places buttons from top
to bottom, 'horizontal' places buttons from left to right.

.. versionadded:: 3.10
"""
super().__init__(ax)

_api.check_in_list(['vertical', 'horizontal'],
layout_direction=layout_direction)
_api.check_isinstance((dict, None), label_props=label_props,
radio_props=radio_props)

Expand All@@ -1619,17 +1650,32 @@ def __init__(self, ax, labels, active=0, activecolor=None, *,
ax.set_yticks([])
ax.set_navigate(False)

ys = np.linspace(1, 0, len(labels) + 2)[1:-1]
if layout_direction == 'vertical':
# Place buttons from top to bottom with buttons at (0.15, y) and labels
# at (0.25, y), where y is evenly spaced within the Axes.
button_ys = label_ys = np.linspace(1, 0, len(labels) + 2)[1:-1]
button_xs = np.full_like(button_ys, 0.15)
label_xs = np.full_like(label_ys, 0.25)
label_ha = 'left'
label_va = 'center'
else:
# Place buttons from left to right with buttons at (x, 0.15) and labels
# at (x, 0.25), where x is evenly spaced within the Axes.
button_xs = label_xs = np.linspace(0, 1, len(labels) + 2)[1:-1]
button_ys = np.full_like(button_xs, 0.15)
label_ys = np.full_like(label_xs, 0.25)
label_ha = 'center'
label_va = 'bottom'

self._useblit = useblit and self.canvas.supports_blit
self._background = None

label_props = _expand_text_props(label_props)
self.labels = [
ax.text(0.25, y, label, transform=ax.transAxes,
horizontalalignment="left", verticalalignment="center",
ax.text(x, y, label, transform=ax.transAxes,
horizontalalignment=label_ha, verticalalignment=label_va,
**props)
for y, label, props in zip(ys, labels, label_props)]
forx,y, label, props in zip(label_xs, label_ys, labels, label_props)]
text_size = np.array([text.get_fontsize() for text in self.labels]) / 2

radio_props = {
Expand All@@ -1642,7 +1688,7 @@ def __init__(self, ax, labels, active=0, activecolor=None, *,
radio_props.setdefault('edgecolor', radio_props.get('color', 'black'))
radio_props.setdefault('facecolor',
radio_props.pop('color', activecolor))
self._buttons = ax.scatter([.15] * len(ys), ys, **radio_props)
self._buttons = ax.scatter(button_xs, button_ys, **radio_props)
# The user may have passed custom colours in radio_props, so we need to
# create the radios, and modify the visibility after getting whatever
# the user set.
Expand Down
2 changes: 2 additions & 0 deletionslib/matplotlib/widgets.pyi
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -157,6 +157,7 @@ class CheckButtons(AxesWidget):
label_props: dict[str, Any] | None = ...,
frame_props: dict[str, Any] | None = ...,
check_props: dict[str, Any] | None = ...,
layout_direction: Literal["vertical", "horizontal"] = ...,
) -> None: ...
def set_label_props(self, props: dict[str, Any]) -> None: ...
def set_frame_props(self, props: dict[str, Any]) -> None: ...
Expand DownExpand Up@@ -210,6 +211,7 @@ class RadioButtons(AxesWidget):
useblit: bool = ...,
label_props: dict[str, Any] | Sequence[dict[str, Any]] | None = ...,
radio_props: dict[str, Any] | None = ...,
layout_direction: Literal["vertical", "horizontal"] = ...,
) -> None: ...
def set_label_props(self, props: dict[str, Any]) -> None: ...
def set_radio_props(self, props: dict[str, Any]) -> None: ...
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp