matplotlib部件(widgets)之单选框(RadioButtons)

危裕
2023-12-01

单选框概述

单选框是图形化界面(GUI)中常见的控件,matplotlib中的单选框属于部件(widgets),matplotlib中的部件都是中性(neutral )的,即与具体后端实现无关。
单选框具体实现定义为matplotlib.widgets.RadioButtons类,继承关系为:Widget->AxesWidget->RadioButtons
RadioButtons类的签名为class matplotlib.widgets.RadioButtons(ax, labels, active=0, activecolor='blue')
RadioButtons类构造函数的参数为:

  • ax:放置单选框的容器,类型为matplotlib.axes.Axes的实例。
  • labels:单选框标签文本列表,类型为字符串列表。
  • actives:单选框的初始选中按钮的索引,类型为整数,默认值为0
  • activecolor:按钮选中时的颜色,默认为蓝色。

RadioButtons类的属性为:

  • ax:放置按钮的容器,类型为matplotlib.axes.Axes的实例。
  • labels:单选框文本列表。
  • circles:单选框中的图形对象,类型为patches.Circle列表。
  • activecolor:单选框被选中时按钮的前景色。
  • value_selected:被选中按钮的标签文本。

RadioButtons类最常用的方法为:

  • on_click(func):参数为回调函数,用于绑定单选框选中事件。
  • set_active(index):根据单选框的索引切换选中/未选中状态。

案例:官方案例

https://matplotlib.org/gallery/widgets/radio_buttons.html
通过单选框选设置曲线颜色、线型。

代码分析

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import RadioButtons

t = np.arange(0.0, 2.0, 0.01)
s0 = np.sin(2*np.pi*t)
s1 = np.sin(4*np.pi*t)
s2 = np.sin(8*np.pi*t)
# 绘制曲线
fig, ax = plt.subplots()
l, = ax.plot(t, s0, lw=2, color='red')
plt.subplots_adjust(left=0.3)
# 构造单选框1
axcolor = 'lightgoldenrodyellow'
rax = plt.axes([0.05, 0.7, 0.15, 0.15], facecolor=axcolor)
radio = RadioButtons(rax, ('2 Hz', '4 Hz', '8 Hz'))

# 编写回调函数,并与单选框1绑定
def hzfunc(label):
    hzdict = {'2 Hz': s0, '4 Hz': s1, '8 Hz': s2}
    ydata = hzdict[label]
    l.set_ydata(ydata)
    # 注意!matplotlib中出现窗体之后的交互中如果修改图像需要重绘图像
    plt.draw()
radio.on_clicked(hzfunc)
# 构造单选框2
rax = plt.axes([0.05, 0.4, 0.15, 0.15], facecolor=axcolor)
radio2 = RadioButtons(rax, ('red', 'blue', 'green'))

# 编写回调函数,并与单选框2绑定
def colorfunc(label):
    l.set_color(label)
    plt.draw()
radio2.on_clicked(colorfunc)
# 构造单选框3
rax = plt.axes([0.05, 0.1, 0.15, 0.15], facecolor=axcolor)
radio3 = RadioButtons(rax, ('-', '--', '-.', 'steps', ':'))

# 编写回调函数,并与单选框3绑定
def stylefunc(label):
    l.set_linestyle(label)
    plt.draw()
radio3.on_clicked(stylefunc)

plt.show()

单选框选中事件回调函数原理解析

以下为RadioButtons类部分源码,根据源码可知,单选框选中事件在内部绑定的是_clicked方法,_clicked方法最终会调用set_active()方法,参数index为被选中复选框的索引,set_active()方法最终调用func(self.labels[index].get_text())funcon_clicked方法绑定的回调函数。所以回调函数func必须调用1个参数即当前选中的单选框的文本标签,如果在定义回调函数时不定义参数就会报错。

self.connect_event('button_press_event', self._clicked)
def _clicked(self, event):
    if self.ignore(event) or event.button != 1 or event.inaxes != self.ax:
        return
    pclicked = self.ax.transAxes.inverted().transform((event.x, event.y))
    distances = {}
    for i, (p, t) in enumerate(zip(self.circles, self.labels)):
        if (t.get_window_extent().contains(event.x, event.y)
                or np.linalg.norm(pclicked - p.center) < p.radius):
            distances[i] = np.linalg.norm(pclicked - p.center)
    if len(distances) > 0:
        closest = min(distances, key=distances.get)
        self.set_active(closest)
def set_active(self, index):
    """
    Select button with number *index*.

    Callbacks will be triggered if :attr:`eventson` is True.
    """
    if 0 > index >= len(self.labels):
        raise ValueError("Invalid RadioButton index: %d" % index)

    self.value_selected = self.labels[index].get_text()

    for i, p in enumerate(self.circles):
        if i == index:
            color = self.activecolor
        else:
            color = self.ax.get_facecolor()
        p.set_facecolor(color)

    if self.drawon:
        self.ax.figure.canvas.draw()

    if not self.eventson:
        return
    for cid, func in self.observers.items():
        func(self.labels[index].get_text())

def on_clicked(self, func):
        """
    Connect the callback function *func* to button click events.

    Returns a connection id, which can be used to disconnect the callback.
    """
    cid = self.cnt
    self.observers[cid] = func
    self.cnt += 1
    return cid
 类似资料: