StellarX v4.0.0 正式发布。
这是一次围绕控件生命周期、界面结构变更、布局能力、重绘稳定性和开发体验进行的系统升级,同时配套上线了包含 16 个章节的完整教程中心。
StellarX 是一个面向 C++ 教学与 Windows 中小型工具开发的轻量级 GUI 框架,帮助开发者从命令行程序自然过渡到结构化的桌面应用开发,同时对GUI框架原理感兴趣的初学者也可以更简单的学习
v4.0.0 不只是增加几个接口,而是进一步完善了 StellarX 的框架基础。
StellarX 是什么?
StellarX 是一个基于 EasyX、面向 Windows 和 C++17 的轻量级 GUI 框架。
它目前提供:
Window窗口和事件循环;Label文本标签;Button普通、切换和禁用按钮;TextBox输入、只读和密码模式;Canvas控件容器;TabControl多页签界面;Table数据表格与分页;Dialog和MessageBox对话框;- 轴向自适应布局系统;
- Tooltip 提示;
- SxLog 日志系统;
- 托管重绘、背景快照和脏区更新机制。
StellarX 适合课程设计、桌面工具、管理界面、数据展示程序,以及希望从 EasyX 基础绘图进一步学习 GUI 框架设计的开发者。
v4.0.0 的核心变化
1. 使用 ControlHandle 管理控件身份
旧代码常在控件交给容器前保存裸指针:
autolabel=std::make_unique<Label>(40,40,"旧文本");Label*labelPtr=label.get();window.addControl(std::move(label));当控件始终存在时,这种方式可能正常工作。但控件一旦被删除、清空或者替换,长期保存的裸指针就可能失效。
v4.0.0 引入了:
StellarX::ControlHandleWindow::addControl()和Canvas::addControl()现在会返回控件句柄:
constautolabelHandle=window.addControl(std::move(label));需要访问控件时,通过所属容器临时查询:
if(Control*control=window.findControl(labelHandle)){static_cast<Label*>(control)->setText("新文本");}句柄只表示控件身份,不代表对象一定仍然存在。
这套设计让业务代码不再需要长期依赖对象地址,也为运行期间安全删除控件提供了基础。
2. Window 和 Canvas 支持受控增删
v4.0.0 为Window和Canvas补充了完整的控件管理接口:
StellarX::ControlHandleaddControl(std::unique_ptr<Control>control);boolremoveControl(StellarX::ControlHandle handle);voidclearControls();Control*findControl(StellarX::ControlHandle handle);std::vector<StellarX::ControlHandle>getControlHandles()const;框架不再向外部暴露内部的unique_ptr容器。
外部代码通过句柄查询、删除和枚举控件,控件所有权仍然由Window或Canvas统一管理。
这使 StellarX 的所有权边界更加明确,也减少了业务代码直接修改内部容器所带来的风险。
3. 回调中可以安全请求修改控件树
GUI 框架中的事件分发通常会遍历控件列表。
如果点击回调在遍历过程中直接删除当前控件,可能造成:
- 迭代器失效;
- 对象提前析构;
- 后续事件访问悬空地址;
- 重绘树与控件树状态不一致。
v4.0.0 增加了结构变更事务。
在点击回调、事件分发或者tick()过程中调用:
window.removeControl(handle);window.clearControls();canvas.addControl(std::move(control));框架会先记录这些结构变更,在最外层事件事务结束后统一提交。
这样既允许业务代码在回调中请求修改界面,又不会破坏当前正在执行的控件遍历。
需要注意:删除请求成功后,业务代码不应继续访问即将被删除的对象。延迟提交是为了保护框架遍历,不是为了让失效对象继续可用。
TabControl API 重新收口
v4.0.0 不再使用旧的TabControl::add(...)接口,而是拆分为两个职责更加明确的方法。
添加页签
conststd::size_t pageIndex=tabs->addTab(std::make_unique<Button>(0,0,120,30,"设置"),std::make_unique<Canvas>(0,0,800,400));addTab()会返回页签的逻辑索引。
向页面添加控件
autorejected=tabs->tryAddToPage(pageIndex,std::make_unique<Label>(24,24,"页面内容"));调用成功时返回空指针。
如果页签索引无效,tryAddToPage()不会直接丢弃控件,而是将unique_ptr所有权返还给调用方。
v4.0.0 同时允许重复页签标题。通过标题查询时只匹配第一个同名页签,因此需要精确定位时,建议保存addTab()返回的索引。
setActiveIndex()现在也会返回bool:
if(!tabs->setActiveIndex(1)){// 页签索引无效}布局系统进一步完善
固定坐标适合简单界面,但窗口允许拉伸后,控件需要明确:
- 是否保持左侧距离;
- 是否保持右侧距离;
- 是否跟随父容器拉伸;
- 是否保持固定尺寸;
- 是否居中;
- 是否按设计位置比例移动。
v4.0.0 推荐分别设置水平轴和垂直轴:
control->setHorizontalAnchors(true,true);control->setHorizontalSizePolicy(StellarX::AxisSizePolicy::Stretch);control->setHorizontalAlignPolicy(StellarX::AxisAlignPolicy::Start);主要策略包括:
StellarX::AxisSizePolicy::Stretch StellarX::AxisSizePolicy::FixedSize以及:
StellarX::AxisAlignPolicy::Start StellarX::AxisAlignPolicy::End StellarX::AxisAlignPolicy::Center StellarX::AxisAlignPolicy::Proportional相比旧的双锚点接口,新布局模型可以更清晰地表达“尺寸是否变化”和“固定尺寸时位置如何变化”。
框架还加入了控件布局能力边界。例如当前Table支持 X 轴拉伸,但 Y 轴仍保持固定,避免不受支持的布局组合破坏控件内部结构。
Table 表格稳定性修复
Table 是 StellarX 中结构相对复杂的控件之一,它内部包含:
- 表头;
- 数据行;
- 列宽和行高计算;
- 上一页、下一页按钮;
- 页码标签;
- 背景快照和重绘范围。
v4.0.0 针对 Table 完成了多项修复:
- 修复运行期间重置数据后,旧分页按钮快照可能覆盖新页码标签的问题;
- 修复分页区域首帧显示不完整的问题;
- 修复极窄宽度下的列宽计算边界;
- 修复列宽总和和 coverage 范围问题;
- 修复 MBCS 文本可能截断半个中文字符的问题;
- 改进分页按钮 hover 和 click 后的视觉恢复;
- 完善表格重置、翻页和页签切换时的重绘行为。
表格数据刷新仍然保持清晰的调用方式:
table->clearData();table->setData({{"1","任务 A","完成"},{"2","任务 B","进行中"}});如果需要同时清空表头和数据:
table->resetTable();需要注意,Table::setData()当前仍然是追加语义,而不是覆盖语义。
重绘系统和显示问题修复
v4.0.0 进行了覆盖范围较大的缺陷修复,重点包括:
- 修复控件移动、缩放和隐藏后可能留下旧像素的问题;
- 修复空 TabControl 的边界情况;
- 修复多层 Canvas、TabControl、Table 和 Dialog 混合遮挡时的错层问题;
- 修复 Tooltip 显示、隐藏和背景快照清理问题;
- 修复 Dialog 关闭后的清理与底层界面恢复;
- 修复局部重绘 coverage 扩张后,上层对话框或浮层漏补画的问题;
- 修复密码掩码按字节生成而不是按逻辑字符生成的问题;
- 修复非法 MBCS 尾字节和中文文本截断问题。
这些问题很多只会在组合场景中出现,例如:
Canvas TabControl Canvas 页面 Table Dialog Tooltipv4.0.0 对托管重绘、持久 coverage、临时浮层和全场景重绘升级条件进行了进一步收口,使复杂界面下的显示行为更加稳定。
SxLog 日志系统改进
StellarX 内置的 SxLog 可以输出到控制台或文件,并支持:
- Trace、Debug、Info、Warn、Error、Fatal;
- Tag 白名单和黑名单;
- 中文和英文文本选择;
- 时间戳、线程 ID 和源码位置;
- 文件滚动;
- RAII 日志行和作用域耗时统计。
基础用法:
StellarX::SxLogger::Get().enableConsole(true);StellarX::SxLogger::Get().setMinLevel(StellarX::SxLogLevel::Debug);SX_LOGI("Demo")<<SX_T("程序启动","Application started");v4.0.0 中,enableFile()和setConfig()都会返回bool:
if(!StellarX::SxLogger::Get().enableFile("stellarx.log",false,1024*1024)){// 文件日志打开失败}如果setConfig()尝试打开新的文件日志失败,框架会保留旧配置和旧文件 sink,不会破坏已经可用的日志通道。
ControlText 字体名称改为拥有型字符串
旧版本中的字体名称字段已经调整为:
std::string faceName;使用方式:
label->textStyle.faceName="微软雅黑";label->textStyle.nHeight=28;label->setDirty(true);ControlText现在自己持有字体名称,不再依赖外部字符数组的生命周期。
两种接入 StellarX 的方式
方式一:使用官方静态库
v4.0.0 官方发布包提供:
Windows x64 MSVC v143库文件包括:
StellarX-v4.0.0-Debug.lib StellarX-v4.0.0-Release.lib配置对应关系:
| 项目配置 | StellarX 库 | 运行库 |
|---|---|---|
| Debug x64 | StellarX-v4.0.0-Debug.lib | /MDd |
| Release x64 | StellarX-v4.0.0-Release.lib | /MD |
官方库适合希望减少业务项目编译单元、快速接入框架的用户。
方式二:直接集成源码
源码结构需要保持为:
StellarX/ ├── include/ │ └── StellarX/ │ ├── StellarX.h │ └── ... └── src/ ├── internal/ │ ├── SxEventLoopInternal.h │ └── SxTextInternal.h ├── Control.cpp ├── Window.cpp └── ...业务项目需要加入src根目录中的 11 个.cpp,并让框架实现能够找到:
src/internal/SxEventLoopInternal.h src/internal/SxTextInternal.h这两个文件属于框架私有实现,业务代码不应直接包含。
源码集成和.lib集成必须二选一。不要同时编译 StellarX.cpp并链接 StellarX.lib。
从旧版本升级需要注意什么?
| 旧写法 | v4.0.0 写法 |
|---|---|
| 长期保存控件裸指针 | 保存ControlHandle,使用时调用findControl() |
Window::getControls() | getControlHandles()/findControl() |
Canvas::getControls() | getControlHandles()/findControl() |
Canvas::clearAllControls() | clearControls() |
TabControl::add(...) | addTab()/tryAddToPage() |
ControlText::lpszFace | ControlText::faceName |
忽略setActiveIndex()结果 | 检查返回的bool |
忽略SxLogger::setConfig()结果 | 检查返回的bool |
升级时不要只替换头文件。
头文件、实现源码和静态库必须来自同一版本,否则可能出现接口已经声明、链接时却找不到实现,或者运行行为与文档不一致的问题。
配套教程中心同步升级
为了降低 StellarX 的入门门槛,v4.0.0 同步更新了完整教程中心。
目前包含 00 到 15 共 16 个章节:
00 教程总览 01 环境安装与版本说明 02 第一个 StellarX 窗口 03 Window 生命周期与事件循环 04 Label / Button / TextBox 基础控件 05 Canvas 容器与控件层级 06 布局系统与窗口自适应 07 Table 表格控件 08 TabControl 页签容器 09 Dialog 与 MessageBox 对话框 10 样式、字体、颜色和背景 11 日志系统与调试建议 12 完整小项目实战:任务清单 13 常见错误与排查 14 使用与构建静态库 15 API 速查表教程不是单纯罗列 API,而是按照真实学习路线组织:
环境配置 ↓ 创建窗口 ↓ 理解控件所有权 ↓ 使用基础控件 ↓ 使用 Canvas 组织界面 ↓ 加入自适应布局 ↓ 学习 Table、TabControl 和 Dialog ↓ 完成一个任务清单小项目教程中的完整示例已经同步迁移到 v4.0.0,不会继续教授已经淘汰的旧接口和长期裸指针写法。
教程中心还提供 AI 助教
教程中心右侧集成了 AI 助教,可以结合当前正在阅读的章节回答问题,例如:
总结本章 解释这段代码 指出本章易错点 生成练习题 用更简单的话解释布局系统快捷指令只会填入输入框,不会直接发送,用户可以根据自己的问题修改后再提问。
AI 适合辅助理解和梳理知识,但具体接口与运行行为仍应以 StellarX v4.0.0 源码、文档和实际测试结果为准。
为什么推荐尝试 StellarX?
StellarX 并不是要隐藏 EasyX,而是希望在保留 C++ 和 EasyX 学习价值的同时,帮助开发者把注意力从重复绘图代码逐步转移到界面结构和业务逻辑上。
使用 StellarX,你可以继续学习:
- C++ 对象生命周期和智能指针;
- GUI 事件循环;
- 控件树和容器;
- 局部坐标与世界坐标;
- 自适应布局;
- 脏区重绘和背景快照;
- 模态与非模态交互;
- 日志、调试和回归测试。
对于刚完成 EasyX 基础学习,希望继续完成更复杂桌面项目的开发者,StellarX 可以作为从“绘制图形”走向“组织 GUI 应用”的下一步。
v4.0.0 发布前验证
本次更新在发布前完成了:
- 全量缺陷修复后的自动化回归;
- 核心场景手工交互检查;
- Debug 和 Release 静态库构建;
- 包内头文件与库文件核对;
- 最小项目编译和链接验证;
- 教程中心完整示例编译检查;
- 旧接口和旧版本内容扫描。
软件测试无法证明程序不存在任何缺陷,但 v4.0.0 已针对当前已知问题和主要使用路径完成系统性收口。
如果在使用过程中发现问题,欢迎通过项目仓库提交可复现步骤、最小代码和运行环境信息。
项目与教程地址
StellarX GitHub 仓库
https://github.com/Ysm-04/StellarX
StellarX v4.0.0 Release
https://github.com/Ysm-04/StellarX/releases/tag/v4.0.0
StellarX 在线教程中心
https://blog.stellarx-gui.top/stellarx-tutorial/
结语
StellarX v4.0.0 的重点不是堆叠更多接口,而是让框架已有能力变得更安全、更明确,也更适合继续扩展。
从ControlHandle、结构变更事务,到新的 TabControl API、轴向布局、重绘修复和日志配置,这些变化共同指向一个目标:
让使用 EasyX 开发 C++ GUI 程序时,界面结构更容易组织,控件生命周期更容易管理,复杂交互也更容易维护。
如果你正在学习 EasyX,或者正在为课程设计、桌面工具和管理程序寻找一套更完整的 GUI 组织方式,可以从 StellarX v4.0.0 和配套教程中心开始体验。
欢迎使用 StellarX,也欢迎为框架提交问题、建议和改进。