Chapter 135 · XUI 基础控件

Radio 单选按钮

Radio 通过 RadioGroup 实现互斥选择,支持水平/垂直排列与自定义指示器。

135

概念

Radio 单选按钮必须配合 RadioGroup 使用:
• RadioGroup:管理一组互斥选项
• 选中一个自动取消其他
• 支持水平/垂直排列方向
• 也可将 CheckCard 加入 Group 实现卡片单选

API 速查

函数说明
int xuiRadioCreate(xui_context pCtx, xui_widget* ppW, const xui_radio_desc_t* pDesc)创建单选按钮
int xuiRadioGroupCreate(xui_context pCtx, xui_widget* ppW, const xui_radio_group_desc_t* pDesc)创建单选组
int xuiRadioGroupAddRadio(xui_widget pGroup, xui_widget pRadio)添加选项
int xuiRadioGroupAddOption(xui_widget pGroup, xui_widget* ppRadio, const xui_radio_desc_t* pDesc)创建并添加
int xuiRadioGroupSetSelectedIndex(xui_widget pGroup, int iIndex)按索引选中
int xuiRadioGroupGetSelectedIndex(xui_widget pGroup)获取选中索引
xui_widget xuiRadioGroupGetSelectedRadio(xui_widget pGroup)获取选中控件
int xuiRadioGroupSetOrientation(xui_widget pGroup, int iOrientation)排列方向
int xuiRadioGroupSetGap(xui_widget pGroup, float fGap)选项间距
int xuiRadioGroupSetChange(xui_widget pGroup, xui_radio_group_change_proc onChange, void* pUser)组变化回调

编译本章示例

gcc -O2 -I. -o ch135.exe ch135_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch135.exe

示例:渲染模式选择

static void OnModeChange(xui_widget pGroup,
    int iIndex, void* pUser)
{
    printf("Render mode: %d\n", iIndex);
}

xui_radio_group_desc_t gDesc = { 0 };
xui_widget pGroup;
xuiRadioGroupCreate(pCtx, &pGroup, &gDesc);
xuiRadioGroupSetChange(pGroup, OnModeChange, NULL);
xuiRadioGroupSetOrientation(pGroup, 1); // 垂直
xuiRadioGroupSetGap(pGroup, 8.0f);

// 添加选项
xuiRadioGroupAddOption(pGroup, NULL,
    &(xui_radio_desc_t){ .sText = "AA-Mesh" });
xuiRadioGroupAddOption(pGroup, NULL,
    &(xui_radio_desc_t){ .sText = "SDF" });
xuiRadioGroupAddOption(pGroup, NULL,
    &(xui_radio_desc_t){ .sText = "Hybrid" });

// 默认选中第一项
xuiRadioGroupSetSelectedIndex(pGroup, 0);
xuiWidgetAddChild(pPanel, pGroup);

完整代码

将以下代码保存为 ch135_main.c,编译后运行即可看到单选组效果:

#include "xge.h"
#include "xui.h"
#include <stdio.h>

static xui_context g_pCtx;

static void OnModeChange(xui_widget pGroup,
    int iIndex, void* pUser) {
    (void)pGroup; (void)pUser;
    printf("Selected: %d\n", iIndex);
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    float mx, my;
    xgeMouseGet(&mx, &my);
    xuiInputPointerMove(g_pCtx, mx, my, 0);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, mx, my, 0, 1);
    if (!xgeMouseDown(XGE_MOUSE_LEFT) /* 释放边沿建议改用事件 */)
        xuiInputPointerUp(g_pCtx, mx, my, 0, 0);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch135 - RadioGroup";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    // 创建单选组
    xui_radio_group_desc_t gDesc = { 0 };
    xui_widget pGroup;
    xuiRadioGroupCreate(g_pCtx, &pGroup, &gDesc);
    xuiRadioGroupSetChange(pGroup,
        OnModeChange, NULL);
    xuiRadioGroupSetOrientation(pGroup, 1);
    xuiRadioGroupSetGap(pGroup, 8.0f);

    // 添加选项
    xuiRadioGroupAddOption(pGroup, NULL,
        &(xui_radio_desc_t){ .sText = "AA-Mesh" });
    xuiRadioGroupAddOption(pGroup, NULL,
        &(xui_radio_desc_t){ .sText = "SDF" });
    xuiRadioGroupAddOption(pGroup, NULL,
        &(xui_radio_desc_t){ .sText = "Hybrid" });
    xuiRadioGroupSetSelectedIndex(pGroup, 0);

    xuiWidgetSetRect(pGroup,
        (xui_rect_t){ 300, 200, 200, 150 });

    xgeRun(onFrame, NULL);

    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiRadioGroupCreate:创建单选组,组内选项互斥。
  • xuiRadioGroupAddOption:一步创建并添加选项,ppRadio 可传 NULL。
  • xuiRadioGroupSetSelectedIndex:编程设置选中项,不触发回调。
  • xuiRadioGroupSetOrientation:0=水平,1=垂直排列。
  • 组变化回调:用户切换选项时触发,参数为新索引。

要点与陷阱

  • 互斥:同组内只能有一个选中,选新自动取消旧。
  • AddOption:一步创建 + 添加,ppRadio 可传 NULL。
  • Orientation:0=水平,1=垂直。
  • 混合:AddCheckCard 可将卡片加入组实现图片单选。

进阶练习

  1. 水平分段选择器:3 个 Radio 紧密排列模拟 SegmentedControl。
  2. 动态选项:运行时添加/删除选项并更新选中。
Radio 单选按钮效果
图:Radio 单选按钮渲染效果