4. 界面基础元素:屏幕与容器,以及常用控件
好,我们正式开始动手了。这一章我会带你认识 TouchGFX 里最基础的几个界面元素——屏幕(Screen)、容器(Container),以及三个最常用的控件:Box、Image 和 Text。
说白了,你后面做的所有界面,都是这些东西拼起来的。就像搭积木,先认识每块积木长什么样,才知道怎么搭。
本章核心:理解 Screen 和 Container 的层级关系,掌握 Box、Image、Text 三个控件的创建与配置方法。
4.1 屏幕(Screen)—— 界面的根
每个 TouchGFX 界面,最顶层就是一个 Screen。你可以把它理解成一张画布,所有控件都画在这张画布上。
我刚开始接触 TouchGFX 时,犯过一个低级错误——试图在一个 Screen 里再放一个 Screen。结果编译报错,查了半天文档才明白:Screen 是唯一的顶层容器,不能嵌套。
我的习惯:在 TouchGFX Designer 里新建项目后,先重命名默认的 Screen。比如叫 MainScreen 或 HomeScreen,别留着 Screen1、Screen2 这种名字。项目大了你就知道好处了。
Screen 的生命周期由框架管理。切换界面时,TouchGFX 会销毁当前 Screen,创建新的 Screen。所以,全局变量或状态不要放在 Screen 类里,否则一切换就丢了。我吃过这个亏,调试了一下午才发现是变量被重置了。
4.2 容器(Container)—— 控件的收纳盒
Container 是什么?说白了就是一个可以装其他控件的控件。它本身不显示任何东西,但你可以用它来分组管理一组控件。
举个例子:你做了一个仪表盘,上面有 5 个温度显示、3 个转速表。如果把它们都直接放在 Screen 上,想整体移动或隐藏时,你得一个一个操作。但如果把它们先放进一个 Container,你只需要操作 Container 一个对象就够了。
| 特性 | Screen | Container |
|---|---|---|
| 层级 | 顶层,不能嵌套 | 子层,可以嵌套多层 |
| 生命周期 | 由框架管理 | 由父容器或 Screen 管理 |
| 可见性 | 始终可见(除非被覆盖) | 可单独设置 visible |
| 典型用途 | 承载整个界面 | 分组、动画、复用 |
注意:Container 的坐标是相对于父容器的。如果你把 Container 放在 (100, 50),里面的子控件坐标 (0, 0) 实际对应屏幕的 (100, 50)。我曾经在嵌套三层 Container 后,找子控件的位置找了半天……嗯,画个坐标图就清楚了。
4.3 Box 控件——最简单的色块
Box 就是纯色矩形。没有边框、没有圆角、没有渐变——就是一个色块。
你可能会问:这么简单的东西有什么用?
用处大了。背景色、分割线、进度条的底色、按钮的填充……很多地方都需要纯色块。而且 Box 的渲染开销极低,适合做大量重复的背景元素。
在 TouchGFX Designer 里拖一个 Box 出来,你只需要设置:
- 位置和大小:x, y, width, height
- 颜色:24 位 RGB,比如
0x2E86C1 - 透明度:0(全透明)到 255(不透明)
代码里创建 Box 也很简单:
// 创建一个蓝色 Box,覆盖整个屏幕作为背景
Box background;
background.setPosition(0, 0, 480, 272);
background.setColor(0x2E86C1);
background.setAlpha(200); // 半透明效果
避坑指南:我曾经用 Box 做按钮背景,但忘了设置 setTouchable(true)。结果按钮点不了,因为 Box 默认不接收触摸事件。如果你需要 Box 响应点击,记得加上这一行。
4.4 Image 控件——图片显示
Image 用来显示图片。TouchGFX 支持 PNG、BMP、JPG 等格式,但最终都会转换成内部格式。
使用 Image 的步骤:
- 准备图片资源:放在项目的
assets/images目录下 - 在 Designer 里添加:从 Image 列表里选择你导入的图片
- 设置位置:x, y 坐标
- (可选)设置缩放:
setScalingAlgorithm选择缩放算法
代码示例:
// 显示一张图标
Image icon;
icon.setXY(100, 50);
icon.setBitmap(Bitmap(BITMAP_MY_ICON_ID)); // 图片 ID 由 TouchGFX 自动生成
重要:TouchGFX 的图片是直接内存映射的,不经过文件系统。所以图片大小直接影响 RAM/Flash 占用。一张 480x272 的 24 位图,未经压缩就是 480×272×3 ≈ 391 KB。如果你的 MCU Flash 只有 1MB,放两张图就满了。我建议:能用纯色 Box 的地方就别用图片,能用 8 位索引色的就别用 24 位真彩色。
4.5 Text 控件——显示文字
Text 控件用来显示字符串。它支持多种字体、颜色、对齐方式。
配置 Text 需要先设置字体(Typography)。在 TouchGFX Designer 的 Text 面板里:
- 选择或新建一个 Typography(字体名称、大小、粗细)
- 设置文字颜色
- 设置对齐方式:左对齐、居中、右对齐
- 输入默认文本(可以留空,运行时动态设置)
代码里动态更新文本:
// 假设界面上有一个 Text 控件叫 textLabel
Unicode::snprintf(textLabelBuffer, TEXT_LABEL_SIZE, "温度: %d°C", temperature);
textLabel.invalidate(); // 刷新显示
注意缓冲区大小:Text 控件内部有一个固定大小的缓冲区。如果你写入的字符串超过缓冲区长度,会截断甚至导致内存越界。我建议:缓冲区大小 = 最大可能字符数 × 2 + 4,给 Unicode 字符留足空间。
另外,中文字体需要额外处理。TouchGFX 默认字体只包含 ASCII 字符。要显示中文,你需要:
- 在
assets/fonts目录下放置中文字体文件(如simhei.ttf) - 在
TouchGFX/target/generated/FontCache.cpp中配置需要包含的汉字范围 - 重新生成代码
嗯,这一步有点麻烦。我一般先列好所有要用到的汉字,生成一个精简字体文件,能省不少 Flash 空间。
4.6 实战:组合使用
来,我们做一个简单的界面:一个带背景色、图标和文字的卡片。
// 在 Screen 的 setupScreen() 中
// 1. 背景 Box
backgroundBox.setPosition(0, 0, 480, 272);
backgroundBox.setColor(0xF0F8FF);
add(backgroundBox);
// 2. 卡片容器
cardContainer.setPosition(40, 60, 400, 150);
cardContainer.setVisible(true);
add(cardContainer);
// 3. 卡片背景
cardBg.setPosition(0, 0, 400, 150);
cardBg.setColor(0xFFFFFF);
cardBg.setAlpha(200);
cardContainer.add(cardBg);
// 4. 图标
iconImage.setXY(20, 25);
iconImage.setBitmap(Bitmap(BITMAP_TEMP_ICON_ID));
cardContainer.add(iconImage);
// 5. 文字
titleText.setPosition(80, 30, 300, 30);
titleText.setTypedText(TypedText(T_TITLE));
titleText.setColor(0x2C3E50);
Unicode::snprintf(titleTextBuffer, TITLE_SIZE, "当前温度");
cardContainer.add(titleText);
valueText.setPosition(80, 70, 300, 50);
valueText.setTypedText(TypedText(T_VALUE));
valueText.setColor(0xE74C3C);
Unicode::snprintf(valueTextBuffer, VALUE_SIZE, "25.5°C");
cardContainer.add(valueText);
你看,一个简单的卡片就做好了。背景是 Box,图标是 Image,文字是 Text,它们都放在 Container 里。想整体移动卡片?改 cardContainer.setXY() 就行。
我的习惯:每个功能模块都用一个 Container 包起来。比如导航栏一个 Container,内容区一个 Container,底部状态栏一个 Container。这样后期维护时,找控件、改布局都特别快。
4.7 本章小结
这一章我们认识了 TouchGFX 的五个基础元素:
- Screen:界面的根,一个界面只有一个
- Container:控件的收纳盒,用于分组管理
- Box:纯色块,轻量级背景元素
- Image:图片显示,注意内存占用
- Text:文字显示,注意缓冲区大小和中文支持