4、UI组件基础:按钮(Button)、文本框(TextArea)、图像(Image)的使用与属性配置

好,咱们今天聊聊TouchGFX里最常用的三个基础组件——按钮、文本框和图像。别看它们基础,我做了这么多项目,发现很多界面问题其实都出在对这三个组件的理解不够深上。你想想看,一个交互界面,用户能点的是按钮,能看到的是图像,能读的是文字。这三个东西用好了,界面就成功了一大半。

4.1 按钮(Button):不只是“点一下”那么简单

按钮是用户和系统交互最直接的入口。在TouchGFX里,按钮本质上是一个可以响应点击事件的图像容器。嗯,这里要注意,它和我们平时理解的“按钮”不太一样——它本身没有固定的形状,全靠你给它贴的图片来定义外观。

4.1.1 按钮的三种状态

一个标准的按钮,至少需要准备两张图片:

  • Released(释放态):按钮没被按下时的样子
  • Pressed(按下态):用户手指或鼠标按下时的样子

我个人习惯再加一张Disabled(禁用态)的图片,虽然它不是必须的。为什么?因为我在项目中遇到过用户快速连点导致界面卡死的情况,后来发现是按钮在禁用状态下没有视觉反馈,用户以为没点到,就一直点。加上禁用态的图片后,问题就解决了。

关键属性配置:

  • Bitmaps(位图):分别指定Released和Pressed状态的图片
  • Alpha(透明度):0-255,255为完全不透明。我一般禁用态设成128
  • Touchable(可触摸):是否响应点击事件。调试时我经常关掉这个

4.1.2 按钮的交互逻辑

按钮的点击事件在TouchGFX里是通过回调函数实现的。说白了,就是你在代码里告诉系统:“当这个按钮被按下时,去执行某某函数”。

// 在视图头文件中声明回调
#include <touchgfx/widgets/Button.hpp>

class MainView : public MainViewBase {
public:
    MainView();
    virtual ~MainView() {}

    virtual void setupScreen();
    virtual void tearDownScreen();

    // 按钮点击回调
    void buttonClickedHandler(const AbstractButton& button);
    
protected:
    Button myButton;
};

// 在源文件中实现
void MainView::setupScreen() {
    // 配置按钮位置和大小
    myButton.setXY(100, 200);
    myButton.setBitmaps(
        Bitmap(BITMAP_BUTTON_RELEASED_ID),   // 释放态图片
        Bitmap(BITMAP_BUTTON_PRESSED_ID)     // 按下态图片
    );
    
    // 绑定回调
    myButton.setAction(buttonClickedHandler);
    add(myButton);  // 别忘了添加到视图
}

void MainView::buttonClickedHandler(const AbstractButton& button) {
    if (&button == &myButton) {
        // 执行你的逻辑
        // 比如切换页面、发送数据等
    }
}

我的小技巧:按钮图片的尺寸最好做成2的倍数,比如80x40、120x60。TouchGFX底层对2的倍数尺寸有优化,渲染性能会好一些。另外,Released和Pressed两张图片的尺寸必须一致,否则切换时界面会跳一下。

4.2 文本框(TextArea):让界面“说话”

文本框是显示文字的基础组件。在TouchGFX里,TextArea和TextAreaWithOneWildcard是两个最常用的。前者显示固定文本,后者可以显示动态内容——比如温度值、设备状态等。

4.2.1 文本的显示机制

TouchGFX的文本渲染和PC上不太一样。它用的是字模(Glyph)方式——每个字符都预先渲染成位图,显示时直接贴图。这样做的好处是速度快,坏处是字体文件会比较大。

属性 说明 我的建议
TypedText 指定使用的文字样式(字体、大小、颜色) 在Texts文件夹里统一管理,别在代码里硬编码
Wildcard 动态内容的占位符,比如显示“温度:%d°C” 用TextAreaWithOneWildcard,别自己拼字符串
Alignment 左对齐、居中、右对齐 中文建议左对齐,英文可以居中
Linespace 行间距,单位像素 默认0,中文建议设2-4,否则字会挤在一起

4.2.2 动态文本的更新

我曾经做过一个温控器项目,需要实时显示温度。一开始我用的是TextArea,每次更新都重新创建字符串,结果内存泄漏了。后来改用TextAreaWithOneWildcard,问题迎刃而解。

// 使用TextAreaWithOneWildcard显示动态数据
class TemperatureView : public TemperatureViewBase {
public:
    void updateTemperature(int temp) {
        // 将整数转换为字符串
        Unicode::snprintf(textBuffer, TEXTBUFFER_SIZE, "%d", temp);
        // 刷新显示
        temperatureText.setWildcard(textBuffer);
        temperatureText.invalidate();
    }
    
protected:
    static const uint16_t TEXTBUFFER_SIZE = 10;
    Unicode::UnicodeChar textBuffer[TEXTBUFFER_SIZE];
    TextAreaWithOneWildcard temperatureText;
};

注意:TextArea的缓冲区大小一定要留够。我见过有人设了5个字符的缓冲区,结果显示“温度:25.5°C”时直接溢出崩溃。建议缓冲区大小至少是实际内容的2倍。

4.3 图像(Image):界面的“颜值担当”

图像组件在TouchGFX里是最灵活的。它不仅可以显示静态图片,还能做缩放、旋转、透明度变化等效果。但要注意,图像组件的性能开销比按钮和文本框大得多。

4.3.1 图像的加载与显示

TouchGFX支持PNG、JPG、BMP等常见格式,但最终都会转换成内部位图格式。我建议所有图片都用PNG,因为它支持透明通道,而且压缩率不错。

// 图像组件的典型用法
Image logoImage;

// 设置位置和大小
logoImage.setXY(50, 50);
logoImage.setBitmap(Bitmap(BITMAP_LOGO_ID));

// 缩放显示(保持宽高比)
logoImage.setScalingMode(Image::SCALE_MODE_KEEP_ASPECT_RATIO);
logoImage.setWidth(200);
logoImage.setHeight(100);

// 设置透明度(实现淡入淡出效果)
logoImage.setAlpha(128);  // 半透明

add(logoImage);

4.3.2 图像的性能优化

图像是界面卡顿的“头号元凶”。我在一个项目里用了10张1920x1080的全屏图片做轮播,结果帧率直接掉到15fps。后来做了三件事才解决:

  • 控制图片尺寸:不要用比显示区域大的图片。比如显示区域是200x100,图片就做成200x100,别用400x200的再缩小
  • 使用压缩格式:TouchGFX支持L8和RGB565格式。L8是256色,适合图标;RGB565是16位色,适合照片
  • 减少Alpha混合:每层透明度叠加都会增加渲染开销。能不用透明就不用

图像格式选择指南:

场景 推荐格式 原因
图标、按钮 L8(256色) 体积小,渲染快,支持透明
照片、背景 RGB565 色彩丰富,16位色够用
需要Alpha渐变 ARGB8888 8位Alpha通道,效果最好但最慢

4.4 三个组件的协同工作

在实际项目中,按钮、文本框和图像很少单独使用。它们通常会组合成一个完整的交互单元。比如一个设置界面:

  • 背景用图像组件显示
  • 标题用文本框显示
  • 操作按钮用按钮组件实现

我习惯在TouchGFX Designer里先把布局搭好,然后再到代码里添加交互逻辑。这样效率最高,而且不容易出错。

布局小技巧:在Designer里,选中多个组件后可以用“Align”工具快速对齐。我经常用“Distribute horizontally”让按钮均匀分布,比手动调坐标快多了。

UI组件基础:按钮、文本框、图像 按钮(Button) 文本框(TextArea) 图像(Image) 三种状态:Released/Pressed/Disabled 回调函数绑定点击事件 图片尺寸需为2的倍数 TypedText定义文字样式 Wildcard实现动态内容 缓冲区大小要留足余量 支持缩放、旋转、透明度 推荐使用PNG格式 控制尺寸避免性能问题 三者协同:图像做背景,文本框显示信息,按钮处理交互 在TouchGFX Designer中布局,在代码中绑定逻辑

好了,这三个组件是TouchGFX界面开发的基石。你先把它们练熟,后面讲容器、列表、滑动页面时,你会发现很多高级组件其实就是这些基础组件的组合和封装。嗯,今天就到这里,动手试试吧。