I am using the matplotlib.widgets
to create radio buttons in my widgets, the buttons coming are stacked vertically, I would like them to be stacked horizontally.
MVCE:
import matplotlib.pyplot as plt
from matplotlib.widgets import RadioButtons
plt.subplots_adjust(left=0.2)
rax = plt.axes([0.5,0.05,0.1,0.1])
radio = RadioButtons(rax ,['1','2','3'], active=0, activecolor='blue' )
plt.show()
As you can see with this example you can get the radio buttons like this
,
I am wondering is there a way to stack these radio buttons horizontally.
There is currently an attempt to introduce an orientation
argument to RadioButtons
in PR #13374; this has not yet been finalized.
As I had commented in this PR, an alternative option would be to use a scatter plot for the buttons. The following shows how I would imagine this implementation. There are two main enhancements compared to the usual buttons:
- Radio buttons are always round independent of the size of the axes.
- They can be aligned arbitrarily, in particular horizontally.
This is achieved by creating a legend internally, which has all the required options readily available. Any valid arguments to Legend
can be used for the Buttons as well.
import matplotlib.pyplot as plt
from matplotlib.widgets import AxesWidget, RadioButtonsclass MyRadioButtons(RadioButtons):def __init__(self, ax, labels, active=0, activecolor='blue', size=49,orientation="vertical", **kwargs):"""Add radio buttons to an `~.axes.Axes`.Parameters----------ax : `~matplotlib.axes.Axes`The axes to add the buttons to.labels : list of strThe button labels.active : intThe index of the initially selected button.activecolor : colorThe color of the selected button.size : floatSize of the radio buttonsorientation : strThe orientation of the buttons: 'vertical' (default), or 'horizontal'.Further parameters are passed on to `Legend`."""AxesWidget.__init__(self, ax)self.activecolor = activecoloraxcolor = ax.get_facecolor()self.value_selected = Noneax.set_xticks([])ax.set_yticks([])ax.set_navigate(False)circles = []for i, label in enumerate(labels):if i == active:self.value_selected = labelfacecolor = activecolorelse:facecolor = axcolorp = ax.scatter([],[], s=size, marker="o", edgecolor='black',facecolor=facecolor)circles.append(p)if orientation == "horizontal":kwargs.update(ncol=len(labels), mode="expand")kwargs.setdefault("frameon", False) self.box = ax.legend(circles, labels, loc="center", **kwargs)self.labels = self.box.textsself.circles = self.box.legendHandlesfor c in self.circles:c.set_picker(5)self.cnt = 0self.observers = {}self.connect_event('pick_event', self._clicked)def _clicked(self, event):if (self.ignore(event) or event.mouseevent.button != 1 orevent.mouseevent.inaxes != self.ax):returnif event.artist in self.circles:self.set_active(self.circles.index(event.artist))
Use it as
plt.subplots_adjust(left=0.2)
rax = plt.axes([0.5,0.05,0.4,0.07])
radio = MyRadioButtons(rax ,['1','2','3'], active=0, activecolor='crimson',orientation="horizontal")plt.show()
Or
rax = plt.axes([0.2,0.5,0.25,0.1])
radio = MyRadioButtons(rax ,["AA", "BB", "CC", "DD"], ncol=2)