Chapter 170 · XUI 数据录入控件

RangeSlider 范围滑块

RangeSlider 双柄范围滑块,选择起止值区间,支持最小/最大间隔限制。

170

概念

RangeSlider 是双滑块区间选择:
• 双柄:Start 和 End 两个滑块手柄
• Fill:两柄之间高亮填充区域
• IntervalLimits:最小/最大间隔约束
• Step:与 Slider 相同的步进吸附
• Orientation:水平或垂直

API 速查

函数说明
int xuiRangeSliderCreate(xui_context pCtx, xui_widget* ppW, const xui_range_slider_desc_t* pDesc)创建范围滑块
int xuiRangeSliderSetRange(xui_widget pW, float fMin, float fMax)总范围
int xuiRangeSliderSetValues(xui_widget pW, float fStart, float fEnd)设置起止值
int xuiRangeSliderGetValues(xui_widget pW, float* pStart, float* pEnd)获取起止值
int xuiRangeSliderSetStep(xui_widget pW, float fStep, float fPageStep)步进
int xuiRangeSliderSetIntervalLimits(xui_widget pW, float fMinInterval, float fMaxInterval)间隔限制
int xuiRangeSliderSetOrientation(xui_widget pW, int iOrientation)方向
int xuiRangeSliderSetMetrics(xui_widget pW, float fTrackSize, float fKnobSize)尺寸
int xuiRangeSliderSetColors(xui_widget pW, uint32_t iTrack, uint32_t iFill, uint32_t iKnob, uint32_t iFocus, uint32_t iDisabled)颜色
int xuiRangeSliderSetChange(xui_widget pW, xui_range_slider_change_proc onChange, void* pUser)变更回调

编译本章示例

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

示例:价格区间筛选

xui_range_slider_desc_t desc = { 0 };

xui_widget pRange;
xuiRangeSliderCreate(pCtx, &pRange, &desc);

xuiRangeSliderSetRange(pRange, 0.0f, 1000.0f);
xuiRangeSliderSetValues(pRange, 200.0f, 800.0f);
xuiRangeSliderSetStep(pRange, 10.0f, 50.0f);

// 最小间隔 50,最大间隔不限
xuiRangeSliderSetIntervalLimits(pRange, 50.0f, 0.0f);

xuiRangeSliderSetChange(pRange, OnPriceChange, NULL);

static void OnPriceChange(xui_widget pW,
    float fStart, float fEnd, void* pUser) {
    FilterByPrice(fStart, fEnd);
}

完整代码

将以下代码保存为 ch170_main.c,编译后运行即可看到 RangeSlider 范围滑块效果:

#include "xge.h"
#include "xui.h"

static xui_context g_pCtx;

static void OnPriceChange(xui_widget pW,
    float fStart, float fEnd, void* pUser) {
    (void)pW; (void)pUser;
    xgeLogWrite("价格区间: %.0f ~ %.0f", fStart, fEnd);
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    xui_vec2_t pos; xgeMouseGet(&pos.x, &pos.y);
    xuiInputPointerMove(g_pCtx, pos.x, pos.y);
    if (xgeMouseDown(XGE_MOUSE_LEFT)) xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
    else xuiInputPointerUp(g_pCtx, pos.x, pos.y, 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 = "ch170 - RangeSlider";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);
    xuiCreate(&g_pCtx);
    /* XGE 官方代理由 xuiProxyXge() 提供 */
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    xui_widget pRoot;
    xuiPanelCreate(g_pCtx, &pRoot, NULL);
    xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 600});

    /* 范围滑块 */
    xui_range_slider_desc_t rsDesc = {0};
    xui_widget pRange;
    xuiRangeSliderCreate(g_pCtx, &pRange, &rsDesc);
    xuiWidgetSetRect(pRange, (xui_rect_t){0, 0, 400, 24});
    xuiWidgetSetRect(pRange, (xui_rect_t){200, 280, 400, 24});
    xuiRangeSliderSetRange(pRange, 0.0f, 1000.0f);
    xuiRangeSliderSetValues(pRange, 200.0f, 800.0f);
    xuiRangeSliderSetStep(pRange, 10.0f, 50.0f);
    xuiRangeSliderSetIntervalLimits(pRange, 50.0f, 0.0f);
    xuiRangeSliderSetChange(pRange, OnPriceChange, NULL);
    xuiWidgetAddChild(pRoot, pRange);

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiRangeSliderCreate:创建双柄范围滑块。
  • SetValues(200, 800):初始区间 200~800。
  • SetStep(10, 50):拖动步进 10,点击轨道跳跃 50。
  • SetIntervalLimits(50, 0):最小间隔 50,最大不限。
  • OnChange:回调同时返回 Start 和 End 两个值。

要点与陷阱

  • Start ≤ End:两柄不可交叉,拖动时自动约束。
  • MinInterval:防止区间过窄(如价格至少差 50)。
  • MaxInterval=0:表示不限制最大间隔。
  • 回调参数:onChange 同时返回 Start 和 End 两个值。

进阶练习

  1. 时间轴裁剪:视频起止时间选择 + 实时预览缩略图。
  2. 双滑块联动数值输入:拖动更新数字框,输入更新滑块位置。
RangeSlider 范围滑块效果
图:RangeSlider 范围滑块渲染效果