10 KiB
10 KiB
功能变更 ID: Feature-20260509-0011
适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
基本信息
- ID: Feature-20260509-0011
- 标题: 布局 API 使用说明与旧接口覆盖规则
- 状态:已验证
- 类型:新增
- 级别:L2 中等
- 模块: Layout API / Control
- 版本 / 分支: 当前工作区
- 环境: Windows + EasyX
- 负责人: Codex 协作修改
变更背景
- 背景:
- 当前布局系统内部已经以
LayoutSpec为统一解算依据。 - 旧接口
setLayoutMode(...)/setAnchor(...)仍然保留,但只能表达有限的双锚点语义。 - 新增公开布局 API 后,需要明确用户应如何设置轴向锚点、尺寸策略和固定尺寸位移策略。
- 当前布局系统内部已经以
- 目标:
- 说明新布局 API 的职责和使用方式。
- 明确新旧接口混用时的覆盖规则。
- 给出常见布局组合和
KEY2迁移场景中的推荐写法。
- 不做什么:[可选]
- 不开放
LayoutCapability的普通外部写入接口。 - 不修改
Table当前版本Y Fixed的能力边界。 - 不处理 Tooltip 智能选位、
Table内部局部重绘、Dialogsynthetic move 统一等后置项。
- 不开放
变更内容
- 变更摘要:
- 增加布局 API 使用说明文档。
- 明确新接口与旧接口的覆盖关系。
- 汇总常见布局模式的代码写法。
- 新增项:[可选]
- 新公开接口说明
- 旧接口映射说明
- 混用覆盖规则
- 常见写法示例
- 调试态日志说明
- 修改项:[可选]
- 无运行时代码修改,本文件只记录使用说明。
- 删除 / 废弃项:[可选]
- 无
- 受影响的文件 / 类 / 函数:
- 对外 API / 属性变化:[可选]
setHorizontalLayoutSpec(...)setVerticalLayoutSpec(...)setHorizontalAnchors(...)setVerticalAnchors(...)setHorizontalSizePolicy(...)setVerticalSizePolicy(...)setHorizontalAlignPolicy(...)setVerticalAlignPolicy(...)getHorizontalLayoutSpec()getVerticalLayoutSpec()
行为对照
- 变更前:
- 用户主要通过
setLayoutMode(...)与setAnchor(...)设置布局。 - 固定尺寸 + 居中、固定尺寸 + 比例位移等组合无法通过旧接口清晰表达。
- 旧双锚点在某些测试场景中会被迫承担 Stretch 语义,导致固定按钮和内容驱动标签在 resize 后错位。
- 用户主要通过
- 变更后:
- 用户可按水平轴 / 垂直轴分别设置锚点集合、尺寸策略和固定尺寸位移策略。
- 旧接口仍可用,但只作为兼容输入层。
- 新旧接口混用时,最后调用的接口覆盖对应轴的布局规格。
- 兼容性说明:兼容
- 迁移说明:[可选]
- 新代码建议优先使用新布局 API。
- 旧代码可以继续使用
setAnchor(...),但复杂布局应逐步迁移到新接口。
验证与落地
- 验证方式:
- 编译
Control.cpp - 编译
z-testDome.cpp /DKEY=2 - 编译
z-testDome.cpp /DKEY=5 - 手测
KEY1 / KEY2 / KEY5
- 编译
- 验证结果:
- 编译级验证通过。
- 用户手测当前暂未发现问题。
- 关联 BUG / Fix:[可选]
- Commit:
- PR:[可选]
- 发布版本:[可选]
- 备注:[可选]
- resize 收口阶段若开启高频 console 日志,可能出现一帧视觉延迟;当前按调试态 I/O 现象记录,不作为 bug 处理。
API 总览
完整轴向规格接口
void setHorizontalLayoutSpec(const StellarX::AxisLayoutSpec& spec);
void setVerticalLayoutSpec(const StellarX::AxisLayoutSpec& spec);
- 直接覆盖对应轴的完整布局规格。
- 调用后自动切换到
StellarX::LayoutMode::AnchorToEdges。 - 适合调用方已经准备好完整
AxisLayoutSpec的场景。
锚点集合接口
void setHorizontalAnchors(bool left, bool right);
void setVerticalAnchors(bool top, bool bottom);
- 水平轴对应
left / right。 - 垂直轴对应
top / bottom。 - 只修改对应轴的锚点集合,不主动改变尺寸策略或位移策略。
尺寸策略接口
void setHorizontalSizePolicy(StellarX::AxisSizePolicy policy);
void setVerticalSizePolicy(StellarX::AxisSizePolicy policy);
Stretch:允许该轴尺寸随父容器变化。FixedSize:该轴尺寸保持设计态尺寸。- 控件能力边界仍然生效。例如
Table当前版本不允许Y Stretch,即使用户设置垂直Stretch,也会被能力边界降级。
固定尺寸位移策略接口
void setHorizontalAlignPolicy(StellarX::AxisAlignPolicy policy);
void setVerticalAlignPolicy(StellarX::AxisAlignPolicy policy);
- 只在
FixedSize语义下决定位置。 - 不负责改变尺寸。
- 常用值:
Start:保持起边关系,例如左固定、上固定。End:保持终边关系,例如右固定、下固定。Center:保持居中关系。Proportional:保持设计态相对位置比例,适合固定尺寸控件在可变宽容器中按比例移动。
读取接口
StellarX::AxisLayoutSpec getHorizontalLayoutSpec() const;
StellarX::AxisLayoutSpec getVerticalLayoutSpec() const;
- 返回当前生效的新模型轴向规格。
- 不保证能完整逆映射回旧
anchor_1 / anchor_2语义。
新旧接口覆盖规则
旧接口仍然保留
void setLayoutMode(StellarX::LayoutMode layoutMode);
void setAnchor(StellarX::Anchor anchor1, StellarX::Anchor anchor2);
- 旧接口是兼容入口。
setAnchor(...)内部会把旧双锚点映射到新的layoutSpec.horizontal与layoutSpec.vertical。- 旧接口无法表达所有新模型状态,例如固定尺寸 + 比例位移、固定尺寸 + 居中等。
后调用者生效
规则:
- 先调用
setAnchor(...),再调用新 API,则新 API 覆盖对应轴规格。 - 先调用新 API,再调用
setAnchor(...),则旧接口重新覆盖水平轴和垂直轴规格。 - 新 API 只覆盖自己负责的轴或字段。例如
setHorizontalSizePolicy(...)只修改水平轴尺寸策略,不修改垂直轴。
示例:
button->setLayoutMode(StellarX::LayoutMode::AnchorToEdges);
button->setAnchor(StellarX::Anchor::Left, StellarX::Anchor::Right);
// 覆盖水平轴:改为固定尺寸 + 居中,不再沿用旧接口映射出的 Stretch。
button->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
button->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Center);
新 API 自动切换布局模式
所有新布局 setter 都会自动将 layoutMode 切换为 AnchorToEdges。
因此新代码通常不需要再额外写:
control->setLayoutMode(StellarX::LayoutMode::AnchorToEdges);
常见布局写法
左固定
control->setHorizontalAnchors(true, false);
control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Start);
右固定
control->setHorizontalAnchors(false, true);
control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::End);
水平拉伸
control->setHorizontalAnchors(true, true);
control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::Stretch);
control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Start);
固定尺寸居中
control->setHorizontalAnchors(true, true);
control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Center);
固定尺寸比例位移
control->setHorizontalAnchors(true, true);
control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Proportional);
适用场景:
- 一组固定尺寸按钮需要随着父容器变宽按比例展开。
KEY2中每个 bit 单元就是该策略的典型使用方式。
KEY2 迁移要点
KEY2 原问题不是单纯参数错误,而是布局单元拆分不合理:
- 位号
Label是内容驱动尺寸。 - 位按钮是固定尺寸。
- 二者分别使用比例位移时,因为自身尺寸不同,resize 后会出现错位。
当前迁移方式:
- 每一位创建一个小
Canvas单元。 - 单元内部固定放置位号
Label与位按钮。 - 单元自身使用
FixedSize + Proportional。 - 这样移动的是整个 bit 单元,而不是标签和按钮分别移动。
示意写法:
auto cell = std::make_unique<Canvas>(cellX, 0, 32, 50);
cell->setHorizontalAnchors(true, true);
cell->setHorizontalSizePolicy(StellarX::AxisSizePolicy::FixedSize);
cell->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Proportional);
能力边界说明
布局 API 表达的是“调用方希望如何布局”,但控件能力边界仍然优先。
当前关键边界:
Canvas:X / Y均允许 Stretch。TabControl:外层允许 Stretch,内部页签栏 / 页面区仍由自身管理。Table:当前版本X Stretch / Y Fixed,这是当前实现边界,不是永久产品结论。TextBox:默认更适合X Stretch / Y FixedSize。Label:默认固定或内容驱动刷新运行态尺寸,不建议做双轴 Stretch。Dialog:只居中,不参与父级拉伸。
如果用户设置的策略超出控件能力边界,统一解算层会按现有降级规则处理,并保留必要日志。
调试态说明
resize / 最大化 / 还原过程中,如果开启大量 console 日志,可能出现一帧视觉延迟或短暂残影。 当前判断原因是日志系统同步写控制台且默认逐行 flush,导致主线程 resize 收口绘制被 I/O 拖慢。
处理建议:
- 常规手测可关闭 console 日志。
- 需要日志时可优先输出到文件。
- 当前不作为布局或重绘 bug 处理,后续可在官网/API 文档中作为调试说明记录。