数值显示格式和组件绘制在 UI 框架中是分立的。
你可以使用下面所列举的 UI 框架里提供的一些数值有关 API 来轻松完成与数值显示有关的任务。
范围与归一化 Numeric Range
1 | NumericRange range; |
| 函数 / API 类型 | API 签名 | 作用说明 |
|---|---|---|
| 构造函数 | constexpr NumericRange() |
创建默认区间对象(范围 [0, 100],步长 1)。 |
| 静态工厂 | static constexpr bool tryCreate(int32_t minimum, int32_t maximum, int32_t step, NumericRange& output) |
校验参数($min \le max$ 且 $step > 0$),成功则写入 output 并返回 true,失败返回 false。 |
| Getter | constexpr int32_t minimum() const |
获取区间的下限值(minimum_)。 |
| Getter | constexpr int32_t maximum() const |
获取区间的上限值(maximum_)。 |
| Getter | constexpr int32_t step() const |
获取区间的变化步长(step_)。 |
| 数值约束 | constexpr int32_t clamp(int32_t value) const |
将输入数值强制限制在 $[minimum, maximum]$ 闭区间内。 |
| 状态检查 | constexpr bool canIncrement(int32_t value) const |
检查 value(经 clamp 后)是否小于上限(能否继续递增)。 |
| 状态检查 | constexpr bool canDecrement(int32_t value) const |
检查 value(经 clamp 后)是否大于下限(能否继续递减)。 |
| 数值运算 | constexpr int32_t incremented(int32_t value) const |
计算 value 增加一个步长后的值,防溢出且最高不超过上限。 |
| 数值运算 | constexpr int32_t decremented(int32_t value) const |
计算 value 减少一个步长后的值,防溢出且最低不低于下限。 |
| 全局函数 | constexpr uint32_t normalizeToExtent(const NumericRange& range, int32_t value, uint32_t extent) |
将 value 在 range 中的位置,四舍五入线性映射到 $[0, extent]$ 区间。 |
clamp()、canIncrement()、canDecrement()、incremented() 和 decremented() 都采用饱和语义。step 不能整除范围时直接落到边界。normalizeToExtent(range, value, pixels) 把 clamp 后的值映射为整数像素长度,舍入规则是最接近整数。
tryCreate() 在 minimum > maximum 或 step <= 0 时返回 false。
数据格式化
NumericFormatter 格式化调用时传入的值,内置策略包括普通整数、补零、缩放整数、后缀和百分比:
1 | IntegerFormat padded{3, nullptr}; |
格式化过程不动态分配内存。Formatter 无效或目标缓冲区不足时,format() 返回 false;只要缓冲区非空,失败后首字节会被置为 \0。拼接 current/total 这类文本时使用 FixedBufferWriter::appendInteger(),不要另写一套整数转换。
Formatter 只保存函数指针和非拥有 context 指针。它引用的 format 配置、suffix 字符串、百分比 range 或自定义 context,必须比所有 format() 调用活得更久。局部 Formatter 可用于立即格式化;被 Widget 保存或随 Popup 排队的 Formatter 必须引用静态存储或持久的 App 成员。
持久依赖应声明在 Formatter 之前,确保成员按反向顺序析构时依赖仍然有效:
1 | NumericRange temperatureRange_{}; |
1. API 接口汇总表(静态工厂与成员函数)
| 模块 / 类 | 接口签名 | 作用说明 |
|---|---|---|
| FixedBufferWriter | FixedBufferWriter(char* buffer, size_t capacity) |
构造函数。绑定外部固定缓冲区与总容量(不持有内存所有权)。 |
bool append(const char* text) |
追加以 \0 结尾的字符串。空间不足则标记失败并返回 false。 |
|
bool appendCharacter(char character) |
追加单个字符。 | |
bool appendInteger(int32_t value, uint8_t minimumDigits = 1U) |
追加有符号 32 位整数,支持设置最少数字位数(前导零补齐)。 | |
bool appendUnsigned(uint32_t value, uint8_t minimumDigits = 1U) |
追加无符号 32 位整数,支持设置最少数字位数(前导零补齐)。 | |
bool finish() |
写入字符串结束符 \0 封口。若成功且未溢出则返回 true。 |
|
bool valid() const |
检查写入器当前状态是否合法(未发生溢出或越界错误)。 | |
size_t size() const |
获取当前已写入的字符数(不包含封口符 \0)。 |
|
| NumericFormatter | static constexpr NumericFormatter custom(const void* context, FormatFunction function) |
静态工厂。创建自定义格式化器,传入自定义上下文与格式化函数指针。 |
static constexpr NumericFormatter integer() |
静态工厂。创建默认整数格式化器(无后缀,无前导零)。 | |
static constexpr NumericFormatter integer(const IntegerFormat& format) |
静态工厂。创建带参数配置的整数格式化器。 | |
static constexpr NumericFormatter scaled(const ScaledIntegerFormat& format) |
静态工厂。创建带缩放因子与小数位的定点数格式化器。 | |
static constexpr NumericFormatter percentage(const PercentageFormat& format) |
静态工厂。基于 NumericRange 计算百分比的格式化器。 |
|
bool format(int32_t value, char* buffer, size_t bufferSize) const |
执行格式化。将 value 格式化并写入到目标 buffer 中。 |
|
constexpr bool valid() const |
检查格式化器是否有效(即是否绑定了合法的格式化函数)。 | |
constexpr const void* context() const |
获取当前绑定的上下文指针。 | |
constexpr FormatFunction function() const |
获取当前绑定的格式化函数指针。 |
2. 配置结构体字段
| 结构体 | 成员字段 | 数据类型 | 默认值 | 作用说明 |
|---|---|---|---|---|
| IntegerFormat | minimumDigits |
uint8_t |
1U |
最少数字位数(不足时自动补前导零)。 |
suffix |
const char* |
nullptr |
后缀字符串(如 "px", "ms")。 |
|
| ScaledIntegerFormat | scale |
uint32_t |
1U |
缩放比例因子(如 100 表示将 1234 格式化为 12.34)。 |
fractionalDigits |
uint8_t |
0U |
保留的小位数。 | |
minimumIntegerDigits |
uint8_t |
1U |
整数部分的最少位数(前导零补齐)。 | |
suffix |
const char* |
nullptr |
后缀字符串。 | |
| PercentageFormat | range |
const NumericRange* |
nullptr |
指向区间对象的指针,用于归一化计算百分比。 |
suffix |
const char* |
"%" |
百分比后缀。 |
数值 Binding 与编辑事务
ValueEditorBinding 非拥有的定义 read/write/notify 边界。
ValueEditSession 才保存 original value、draft value 和编辑策略。
1 | static void changed(void* context, int32_t value) { |
CommitOnConfirm 下,draft 只存在 Session 中;commit() 才写回并通知,cancel() 直接丢弃 draft。Live 下,每次成功的 setDraftValue() 都立即写回并通知;cancel() 会恢复 original value,并通知这次恢复。只用初始整数构造的 Session 没有外部 Binding,但仍走相同的 draft/commit/cancel 路径。
| 操作 | CommitOnConfirm |
Live |
|---|---|---|
setDraftValue(value) |
只更新 draft | 先写回、通知,再更新 draft |
commit() |
值有变化时写回并通知;把 draft 设为新的 original | 把当前 draft 设为新的 original |
cancel() |
丢弃 draft | 值有变化时恢复并通知 original value |
Session 无效或必要写入失败时,这三个操作都会返回 false。写入失败不会推进事务状态;调用者应保持编辑器打开,或用 draftValue() 恢复可见控件。
Binding 的 value context 和 changed context 都是非拥有的,必须覆盖 Session 及其全部操作的寿命。Popup 请求复制 Binding 后,这项要求会延长到 pending 排队期和 active 显示期全部结束。
1. Namespace Function
| 接口签名 | 作用说明 |
|---|---|
bool formatScaledInteger(char* buffer, size_t bufferSize, int32_t raw, uint32_t scale, uint8_t fractionalDigits, const char* suffix = nullptr) |
底层格式化工具函数。将定点数原始值 raw 结合 scale 缩放因子格式化为带指定小数位数(fractionalDigits)和可选后缀(suffix)的字符串,写入指定缓冲区。 |
2. API 接口 (PixelUIValue::Binding 静态工厂与成员函数)
| 接口签名 | 作用说明 |
|---|---|
constexpr Binding() |
默认构造函数。创建一个空绑定对象(未关联数据对象与格式化函数)。 |
static constexpr Binding custom(const void* object, FormatFunction formatter, const char* suffix = nullptr) |
静态工厂。创建自定义绑定对象,显式传入绑定的对象指针、自定义格式化函数及可选后缀。 |
static constexpr Binding integer(const int32_t& value, const char* suffix = nullptr) |
静态工厂。绑定一个 int32_t 变量引用,生成以整数形式格式化该变量的绑定对象。 |
template <uint8_t FractionalDigits, int32_t Scale> static constexpr Binding decimal(const ScaledInt32<Scale>& value, const char* suffix = nullptr) |
静态工厂模板。绑定一个 ScaledInt32<Scale> 定点数变量引用,生成带指定小数位数(FractionalDigits <= 9)的格式化绑定对象。 |
bool format(char* buffer, size_t bufferSize) const |
执行格式化。调用绑定的格式化函数将关联数据格式化至 buffer。若失败或无效,自动清空缓冲区(置 \0)并返回 false。 |
constexpr const void* object() const |
Getter。获取绑定的目标对象指针(object_)。 |
constexpr FormatFunction formatter() const |
Getter。获取绑定的格式化函数指针(formatter_)。 |
constexpr const char* suffix() const |
Getter。获取绑定的后缀字符串指针(suffix_)。 |
组件中有对这些功能的利用,可作为示例学习
NumScroll用NumericRange步进,用NumericFormatter生成文字。使用setRange(min, max, step)或setRange(range),再用setFormatter(formatter)配置显示。PopupProgress的 LEFT/RIGHT 使用range.step(),进度条几何单独做整数归一化,显示文字完全由 Formatter 决定。PopupValueDigits使用ValueEditSession;构造不会修改外部值。数字位上的 SELECT 只结束该位的局部编辑,之后仍可修改其他位。OK 提交整个 Session;CANCEL 或 BACK 取消。


