调试工具 Debug
写 UI 最痛苦的不是画不出来,而是不知道为什么没画出来。HiEasyX 提供两套内置调试工具:
ShowMetricsWindow看性能与状态,ShowLayoutDebugger看布局边界。它们不占额外窗口,直接在当前 IMGUI 上下文里绘制,用完即走。
使用前提
必须在 End() 之前调用
HX::Window(HXStr("main"), wp);
// ... 你的控件 ...
HX::ShowMetricsWindow(); // ✅ 正确:在 End() 之前
HX::ShowLayoutDebugger(); // ✅ 正确:在 End() 之前
HX::End();
如果在 End() 之后调用,LayoutStack 已经被清空,调试器拿不到布局上下文,会显示空内容或触发断言。
ShowMetricsWindow
函数原型
void ShowMetricsWindow();
无参数,无返回值。
显示内容
调用后会在当前窗口内渲染一个调试面板,包含以下信息:
| 类别 | 内容 |
|---|---|
| 帧时间 | 上一帧耗时(ms)与估算 FPS。 |
| 消息统计 | 本帧接收到的 peekmessage 数量,按类型分布。 |
| 池统计 | HXSubPainterPool 的桶数量、总 painter 数、命中/未命中情况。 |
| 栈深度 | 当前 LayoutStack 深度、WindowStack 深度、Focus Stack 深度。 |
什么时候打开
建议在开发模式下绑定一个快捷键(如 Ctrl+Shift+M)或菜单项来切换显示:
static bool showMetrics = false;
if (HX::Button(HXStr("Toggle Metrics"), btn)) {
showMetrics = !showMetrics;
}
if (showMetrics) {
HX::ShowMetricsWindow();
}
ShowLayoutDebugger
函数原型
void ShowLayoutDebugger();
无参数,无返回值。
显示内容
在当前窗口上方叠加绘制半透明矩形,每个矩形对应 LayoutStack 中的一个布局上下文:
- BaseLine:布局当前行的基线 Y 坐标。
- **CurrentHeightMax`:当前行最大高度。
- 宽度与高度:当前可用内容区域的尺寸。
颜色约定
- 不同层级的布局矩形用不同颜色区分(通常是红、绿、蓝、黄循环)。
- 文字标签直接画在矩形内部或边缘,不影响控件点击。
典型用途
| 问题 | 用 LayoutDebugger 诊断 |
|---|---|
| 控件莫名其妙换行 | 看当前 LayoutStack 的可用宽度是否被意外缩小。 |
| 垂直间距不对 | 看 BaseLine 和 CurrentHeightMax 的推进是否符合预期。 |
| 嵌套容器里控件跑出边界 | 看外层 Panel / Scroller / Viewport 的 clip rect 是否设置正确。 |
| 对齐异常 | 看 BeginHorizontal / BeginVertical 引入的新布局上下文。 |
完整示例:开发模式开关
#include <include/hex.h>
#include <include/impl/EasyX/hex_impl_easyx.h>
void DemoDebugTools() {
static bool showMetrics = false;
static bool showLayout = false;
HX::WindowProfile wp;
wp.Title = HXStr("Debug Demo");
wp.Size = {600, 500};
HX::Window(HXStr("debug_demo"), wp);
// 调试开关
HX::BeginHorizontal();
HX::CheckboxProfile cb1;
cb1.Checked = showMetrics;
if (HX::Checkbox(HXStr("Show Metrics"), cb1)) {
showMetrics = cb1.Checked;
}
HX::CheckboxProfile cb2;
cb2.Checked = showLayout;
if (HX::Checkbox(HXStr("Show Layout"), cb2)) {
showLayout = cb2.Checked;
}
HX::EndHorizontal();
// 一些普通控件,用来观察布局
HX::Text(HXStr("Line 1: Hello Debug"));
HX::Text(HXStr("Line 2: More content here"));
HX::ButtonProfile btn;
HX::Button(HXStr("A Button"), btn);
HX::BeginHorizontal();
HX::Button(HXStr("Left"), btn);
HX::Button(HXStr("Right"), btn);
HX::EndHorizontal();
// ========== 调试工具必须在 End() 之前 ==========
if (showMetrics) {
HX::ShowMetricsWindow();
}
if (showLayout) {
HX::ShowLayoutDebugger();
}
HX::End();
}
与其他调试手段配合
控制台日志
EasyX 程序通常是 WinMain / main 子系统。如果你想看 printf 输出,可以在 main 开头加:
AllocConsole();
freopen("CONOUT$", "w", stdout);
然后结合 ShowMetricsWindow 的数值做实时对比。
SubPainter 泄漏检测
如果 MetricsWindow 里的池统计数字随时间无限增长,说明某个控件在直接 new / delete SubPainter 而没有走 HXSubPainterPool。这是性能回归的典型信号。
总结
| 工具 | 看什么 | 调用位置 |
|---|---|---|
ShowMetricsWindow | 帧时间、FPS、消息数、池统计、栈深度 | End() 之前 |
ShowLayoutDebugger | LayoutStack 各层边界、基线、行高 | End() 之前 |
调试工具是框架的自省能力。打开它们,你看到的不再是一团黑箱,而是一层一层剥开的清晰结构 🔍