Chapter 168 · XUI 数据录入控件

TagInput 标签输入

TagInput 标签输入框,输入文本后回车生成标签,支持删除、最大数量、长度限制。

168

概念

TagInput 是标签式多值输入控件:
• Tag:每个标签是一个文本胶囊,带删除按钮
• 输入区:标签后方的文本输入区域
• Commit:回车/逗号/失焦时将输入转为标签
• MaxTags:限制最大标签数量
• MaxLength:限制单个标签文本长度

API 速查

函数说明
int xuiTagInputCreate(xui_context pCtx, xui_widget* ppW, const xui_tag_input_desc_t* pDesc)创建标签输入
int xuiTagInputAddTag(xui_widget pW, const char* sText)添加标签
int xuiTagInputRemoveTag(xui_widget pW, int iIndex)删除标签
int xuiTagInputClearTags(xui_widget pW)清除全部
int xuiTagInputSetTags(xui_widget pW, const char* const* ppTags, int iCount)批量设置
int xuiTagInputGetTagCount(xui_widget pW)标签数量
int xuiTagInputCommit(xui_widget pW)提交当前输入
int xuiTagInputSetPlaceholder(xui_widget pW, const char* sText)占位文本
int xuiTagInputSetMaxTags(xui_widget pW, int iMaxTags)最大数量
int xuiTagInputSetMaxLength(xui_widget pW, int iMaxLength)最大长度
int xuiTagInputSetChange(xui_widget pW, xui_tag_input_change_proc onChange, void* pUser)变更回调

编译本章示例

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

示例:关键词标签

xui_tag_input_desc_t desc = { 0 };

xui_widget pTagInput;
xuiTagInputCreate(pCtx, &pTagInput, &desc);

xuiTagInputSetPlaceholder(pTagInput, "输入关键词,回车添加");
xuiTagInputSetMaxTags(pTagInput, 10);
xuiTagInputSetMaxLength(pTagInput, 20);

// 预设标签
const char* tags[] = { "C99", "图形引擎", "跨平台" };
xuiTagInputSetTags(pTagInput, tags, 3);

xuiTagInputSetChange(pTagInput, OnTagsChange, NULL);

static void OnTagsChange(xui_widget pW, int iAction,
    int iIndex, void* pUser) {
    int n = xuiTagInputGetTagCount(pW);
    UpdateFilter(n);
}

完整代码

将以下代码保存为 ch168_main.c,编译后运行即可看到 TagInput 标签输入效果:

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

static xui_context g_pCtx;

static void OnTagsChange(xui_widget pW, int iAction,
    int iIndex, void* pUser) {
    (void)iIndex; (void)pUser;
    int n = xuiTagInputGetTagCount(pW);
    xgeLogWrite("标签变更 action=%d, 当前数量=%d", iAction, n);
}

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 = "ch168 - TagInput";
    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_tag_input_desc_t tiDesc = {0};
    xui_widget pTag;
    xuiTagInputCreate(g_pCtx, &pTag, &tiDesc);
    xuiWidgetSetRect(pTag, (xui_rect_t){0, 0, 400, 36});
    xuiWidgetSetRect(pTag, (xui_rect_t){200, 250, 400, 36});
    xuiTagInputSetPlaceholder(pTag, "输入关键词,回车添加");
    xuiTagInputSetMaxTags(pTag, 10);
    xuiTagInputSetMaxLength(pTag, 20);

    const char* tags[] = { "C99", "图形引擎", "跨平台" };
    xuiTagInputSetTags(pTag, tags, 3);
    xuiTagInputSetChange(pTag, OnTagsChange, NULL);
    xuiWidgetAddChild(pRoot, pTag);

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

代码讲解

  • xuiTagInputCreate:创建标签输入控件。
  • SetMaxTags(10):最多允许 10 个标签。
  • SetTags:预设 3 个初始标签。
  • OnChange:标签增删时触发,iAction 区分添加/删除/清除。
  • 回车提交:用户输入文本后按回车自动生成标签胶囊。

要点与陷阱

  • Commit 触发:回车、逗号、分号、失焦均可触发标签提交。
  • MaxTags:达到上限后输入区禁用,不再接受新标签。
  • Change Action:0=添加, 1=删除, 2=清除。
  • 空文本:空白输入不会生成标签(自动忽略)。

进阶练习

  1. 邮件收件人:TagInput + 自动补全建议列表。
  2. 重复检测:添加前检查是否已存在相同标签。
TagInput 标签输入效果
图:TagInput 标签输入渲染效果