你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

F429I-DISC1体验报告(3) 画板线条绘制和调色功能的实现丨国庆开发板测评活动

[复制链接]
cm32 发布时间:2025-12-3 15:29

综述

本文将完成以下任务

使用触摸屏功能,实现一个简单的绘图应用,用户可以用手指在屏幕上绘制线条。

我们将实现一个画面,具有绘制区域,预设颜色按钮、清屏按钮、调色盘等功能。画布中使用Line类来模拟绘制的曲线;颜色按钮和调色盘用于设置画笔颜色,调色盘通过调节R,G,B的值调节画笔颜色,并且实时将颜色显示在调色盘按钮上;Clear按钮用于清空画布内容。

开发工具

TouchGFX Designer 4.26.0,STM32CubeIDE 2.0.0,STM32CubeMX

GUI绘制

  • 在新建或者复制项目文件后,先新建一个Screen(我在上一个项目的基础上编辑),修改名称为SketchPad;如果有其他画面存在的话,先设置为Startup Screen,方便后续调试;勾选 Canvas Buffer 并设置大一些,这个大小将决定画布能画多少条线。

image.png

  • 点击Containers添加并绘制自定义的控件,用于画布的实现,负责实际“绘制”逻辑,不与Screen混合,结构更清晰,也可以避免很多问题:

image.png

将新建后的Container重命名为SketchContainer,调整大小为W240×H260

image.png

  • 返回Screens,添加自定义的SketchContainer组件,并且勾选Mixins中的ClickListener,确保能响应绘制时的点击事件;

image.png

  • 添加FlexButton控件,调整大小为W30×H30,设置Box With Border元素的Border Size 边框尺寸为3,颜色设置为对应按钮颜色,复制并放置红、橙、黄、绿、蓝、紫、黑和一个预留的调色盘按钮。

image.png

复制多个按钮,因为按钮较多,为了方便辨认,最好给每个按钮都命名。修改按钮颜色、文本内容并排版后的样式如下:

其中调色盘按钮(ColorChooseBtn)的Visual Elements中加入文本元素"...",清屏按钮(ClearBtn)加入文本元素"Clear"。

image.png

  • 接下来绘制调色盘的弹窗,首先添加一个 ModalWindow,底图选择较大的240×270的边框。

image.pngimage-20251202151323858

  • 绘制滑块控件,在Images中导入绘制滑动控件用的三个颜色的长条和小球,如图所示。

image.png

添加一个Slider,不需要选择预设,直接进行Image的替换: 原本的track_medium.png替换成我们自己的track,filler_medium.png替换成我们自己的filler,同样的,滑块也替换成自己的小球。

image.png

设置Indicator Position(小球的位置)的最大值为160,因为长条的最大值只有160,否则小球能够划出画布范围;同时设置Values数值范围为0到255,表示8位颜色。

image.png

复制三个Slider并分别设置控件为对应颜色的图片,记得将三个控件拖到弹窗ColorSetmodalWindow里面,并分别修改名称,调整位置后的布局如下:

image.png

  • 接下来在3个滑块的后面加入一个文本,使拉动滑块的同时会显示对应的数值:

添加一个Text Area,在Translation下面有一个wildcard的"➕",点击加号添加一个通配符;

输入Wildcard1 的文本ID、初始值,并勾选Use wildcard buffer,buffer的大小使用默认的10即可。在后续交互中会实现Slider和Text Area的绑定。

image.png

同样的,将Text Area复制三份,并在控件树中拖到弹窗ColorSetmodalWindow里面,分别修改名称为GreenValue,BlueValue,RedValue;

image.png

同时,注意GreenValue、BlueValue的Wildcard ID需要删除并重新设置,否则后面无法正常显示。 image.png

在Texts -> Typographies里面修改Wildcard对应的字体预设,在Wildcard Characters中添加数字字符,才能确保动态显示的数字不会变成??? image.png

  • 在modalWindow容器中添加一个FlexButton按钮控件,修改名称为ColorConfirmBtn,即颜色设置的确认按键,将按钮的边框大小调为0,只保留填充颜色。

!image.png

交互设计

因为TouchGFX没有提供原生的小画板控件,我们必须通过额外的代码来实现绘制线条的功能。

CubeIDE编写代码

找到项目文件夹中的<项目名>/STM32CubeIDE,双击.project或者.cproject打开CubeIDE项目文件。

image.png

在项目中的Application/User/gui中有两个和SketchPad这个窗口有关的文件,分别是SketchPadPresenter.cpp和SketchPadView.cpp;以及一个SketchContainer.cpp的自定义组件的源文件,双击打开它们。

image.png

SketchContainer作为自定义控件,响应在Container内触发的点击和拖拽事件,并直接完成线段绘制;

SketchPadView和SketchPadViewBase作为UI层,实现了可视化控件的绘制和交互事件处理,sketchContainer1在SketchPadViewBase.hpp中声明,可以通过SketchPadView的继承,在SketchPadView中调用;

同时SketchPadPresenter作为逻辑层,虽然不能直接使用SketchPadViewBase中声明的变量和函数,但是可以通过SketchPadView& view这一私有变量的声明,实现对Container的接口的调用;同时presenter又在父类View.hpp中作为保护段变量被声明,这一设计使得SketchPadPresenter中实现的接口可以在SketchPadViewBase 自动生成回调函数中中通过presenter -> <函数名> 被调用。

image.png


SketchContianer

首先修改SketchContianer的源文件和头文件,按住Ctrl并单击.cpp上include的头文件可以直接打开SketchContianer.hpp。

image.png

SketchContianer.hpp的内容如下,主要是实现了点击和拖拽响应以及线条绘制、同时提供了清屏、修改颜色的接口。代码中已经加以注释,以供参考:

#ifndef SKETCHCONTAINER_HPP
#define SKETCHCONTAINER_HPP

#include <gui_generated/containers/SketchContainerBase.hpp>
#include <touchgfx/widgets/canvas/Line.hpp>        // Canvas 模式的直线控件
#include <touchgfx/widgets/canvas/PainterRGB565.hpp> // RGB565 画笔,用于为 Line 上色

/* 每一条用户绘制的线段都使用一个 LineNode 保存:
// 包含 Line 控件对象、画笔对象、起点与终点像素坐标。
 TouchGFX 的 Line 实际上只会画一条直线,曲线效果靠多条直线逼近。*/
struct LineNode
{
    touchgfx::Line line;               // TouchGFX 的可绘制直线控件
    touchgfx::PainterRGB565 painter;   // 为 Line 提供颜色、位深格式的画笔

    int16_t sx, sy;   // 当前线段的起点(屏幕坐标)
    int16_t ex, ey;   // 当前线段的终点(屏幕坐标)
};

/* SketchContainer内部有白色画布与所有的线段控件。*/
class SketchContainer : public SketchContainerBase
{
public:
    SketchContainer();
    virtual ~SketchContainer() {}

    virtual void initialize();   // 初始化画布与所有 LineNode(隐藏但预加入容器)

    enum { MAX_LINES = 600 };    // 最多同时存储 600 条线,避免 RAM 爆炸,可根据实际情况调整大小

    // 在本容器中拦截触摸事件,以实现绘图
    virtual void handleClickEvent(const touchgfx::ClickEvent& event) override;
    virtual void handleDragEvent(const touchgfx::DragEvent& event) override;

    void clear();                            // 清除所有线段并隐藏
    void setColor(touchgfx::colortype c);    // 设置当前绘图颜色(改变画笔颜色)

protected:
    LineNode lines[MAX_LINES];     // 所有预创建的线段,循环使用,避免动态分配内存

    int      lineCount;            // 当前已经绘制的有效线段数量
    bool     touchActive;          // 是否正在绘制(按需使用)
    bool     fingerDown;           // 手指是否按下(用于状态机)
    int16_t  lastX;                // 上一个触摸点 X(用于平滑)
    int16_t  lastY;                // 上一个触摸点 Y(用于平滑)
    touchgfx::colortype currentColor; // 画笔颜色

    // Canvas 的区域(用户允许绘图的矩形区域)
    enum { CANVAS_X = 0 };
    enum { CANVAS_Y = 0 };
    enum { CANVAS_W = 240 };
    enum { CANVAS_H = 260 };

    // 判断新线段是否与旧线段太接近(避免重复绘制造成锯齿或污点)
    bool willOverlap(int x0, int y0, int x1, int y1);

    // 判断当前触摸点是否在画布区域内
    bool insideCanvas(int16_t x, int16_t y) const;
};

#endif // SKETCHCONTAINER_HPP

下面是SketchContainer.cpp的内容。

#include <gui/containers/SketchContainer.hpp>
#include <touchgfx/Color.hpp>

/**
 * @brief 构造函数,初始化绘图容器的内部状态
 *
 * @note 默认画笔颜色为黑色,容器触摸功能自动开启。
 */
SketchContainer::SketchContainer()
    : lineCount(0),
      touchActive(false),
      fingerDown(false),
      lastX(0),
      lastY(0)
{
    setTouchable(true); ///< 必须允许接收触摸事件才能手写绘制
    currentColor = touchgfx::Color::getColorFromRGB(0,0,0);
}

/**
 * @brief 初始化画布与所有线段对象
 *
 * @note TouchGFX CanvasWidgetRenderer 需要提前 add() 所有 Line 元素。
 * @note 线段初始化为不可见,绘制时才设置 Visible。
 */
void SketchContainer::initialize()
{
    SketchContainerBase::initialize();

    // 设置白色画布
    box1.setPosition(CANVAS_X, CANVAS_Y, CANVAS_W, CANVAS_H);
    box1.setColor(touchgfx::Color::getColorFromRGB(255,255,255));

    // 初始化线段池(静态分配,避免动态内存)
    for (int i = 0; i < MAX_LINES; i++)
    {
        LineNode& node = lines[i];

        node.sx = node.sy = 0;
        node.ex = node.ey = 0;

        node.line.setPosition(CANVAS_X, CANVAS_Y, CANVAS_W, CANVAS_H);
        node.painter.setColor(currentColor);
        node.line.setPainter(node.painter);
        node.line.setLineWidth(2);
        node.line.setLineEndingStyle(touchgfx::Line::ROUND_CAP_ENDING);
        node.line.setVisible(false);

        add(node.line); ///< 加入容器供 CanvasWidgetRenderer 使用
    }
}

/**
 * @brief 判断触摸点是否处于画布区域内
 *
 * @param x 屏幕 X 坐标
 * @param y 屏幕 Y 坐标
 * @return true 触摸点在画布内
 * @return false 触摸点不在画布内
 */
bool SketchContainer::insideCanvas(int16_t x, int16_t y) const
{
    return (x >= CANVAS_X && x < CANVAS_X + CANVAS_W &&
            y >= CANVAS_Y && y < CANVAS_Y + CANVAS_H);
}

/**
 * @brief 跳点判定(用于去除异常快速位移)
 *
 * @param x1 上一点 X
 * @param y1 上一点 Y
 * @param x2 当前点 X
 * @param y2 当前点 Y
 * @return true 表示属于跳点,应忽略
 */
static inline bool isJump(int x1, int y1, int x2, int y2)
{
    int dx = x2 - x1;
    int dy = y2 - y1;
    int d2 = dx * dx + dy * dy;

    return (d2 > 30 && d2 < 120);
}

/**
 * @brief 一阶平滑滤波
 *
 * @param oldValue 旧数据
 * @param newValue 新数据
 * @return 平滑后的结果
 */
static inline int smooth(int oldValue, int newValue)
{
    return (oldValue + newValue * 3) / 4;
}

/**
 * @brief 二阶平滑滤波(未使用)
 *
 * @param x2 上上帧
 * @param x1 上一帧
 * @param n 当前帧
 * @return 滤波输出值
 */
inline int16_t smooth2(int16_t x2, int16_t x1, int16_t n)
{
    return (x2 + x1 * 2 + n) >> 2;
}

/**
 * @brief 判断新线段是否会覆盖旧线段
 *
 * @param x0 旧点 X
 * @param y0 旧点 Y
 * @param x1 新点 X
 * @param y1 新点 Y
 * @return true 距离过近,视为覆盖,应禁止绘制
 * @return false 无覆盖,可绘制
 */
bool SketchContainer::willOverlap(int x0, int y0, int x1, int y1)
{
    const int minDist2 = 9;

    for (int i = 0; i < lineCount; i++)
    {
        const LineNode& LN = lines[i];

        int dx = LN.sx - x1;
        int dy = LN.sy - y1;
        if (dx * dx + dy * dy < minDist2) return true;

        dx = LN.ex - x1;
        dy = LN.ey - y1;
        if (dx * dx + dy * dy < minDist2) return true;
    }
    return false;
}

/**
 * @brief 处理触摸按下与释放事件
 *
 * @param e TouchGFX ClickEvent 事件
 *
 * @note 按下点必须在画布内,才能开始绘制。
 */
void SketchContainer::handleClickEvent(const touchgfx::ClickEvent& e)
{
    if (e.getType() == touchgfx::ClickEvent::PRESSED)
    {
        fingerDown = true;
        lastX = e.getX();
        lastY = e.getY();

        if (!insideCanvas(lastX, lastY))
            fingerDown = false;
    }
    else if (e.getType() == touchgfx::ClickEvent::RELEASED)
    {
        fingerDown = false;
        touchActive = false;
    }

    SketchContainerBase::handleClickEvent(e);
}

/**
 * @brief 处理拖动事件,实现连续绘图
 *
 * @param e TouchGFX DragEvent 事件
 *
 * @note 逻辑包括:
 *       - 检查是否在画布内
 *       - 平滑处理
 *       - 跳点过滤
 *       - 覆盖检测
 *       - 生成线段并渲染
 */
void SketchContainer::handleDragEvent(const touchgfx::DragEvent& e)
{
    if (!fingerDown) return;

    int rx = e.getNewX();
    int ry = e.getNewY();

    if (!insideCanvas(rx, ry))
    {
        fingerDown = false;
        return;
    }

    // 一阶平滑
    int x = (lastX + rx * 3) >> 2;
    int y = (lastY + ry * 3) >> 2;

    // 微小移动忽略
    if (abs(x - lastX) < 2 && abs(y - lastY) < 2)
        return;

    if (willOverlap(lastX, lastY, x, y))
        return;

    if (lineCount >= MAX_LINES)
        return;

    LineNode& node = lines[lineCount];

    node.sx = lastX;
    node.sy = lastY;
    node.ex = x;
    node.ey = y;

    node.painter.setColor(currentColor);
    node.line.setPainter(node.painter);
    node.line.setLineWidth(2);
    node.line.setVisible(true);

    node.line.setStart(node.sx - CANVAS_X, node.sy - CANVAS_Y);
    node.line.setEnd(node.ex - CANVAS_X, node.ey - CANVAS_Y);

    node.line.invalidate();

    lastX = x;
    lastY = y;
    lineCount++;
}

/**
 * @brief 清除全部线段,将画布恢复为空白
 *
 * @note 仅隐藏线段,不释放对象。
 */
void SketchContainer::clear()
{
    for (int i = 0; i < lineCount; i++)
    {
        lines[i].line.setVisible(false);
        lines[i].line.invalidate();
    }
    lineCount = 0;
}

/**
 * @brief 设置当前绘图颜色
 *
 * @param c RGB565 颜色值
 */
void SketchContainer::setColor(touchgfx::colortype c)
{
    currentColor = c;
}

SketchPadView

SketchPadView.cpp完全不需要修改,只需要在SketchPadView.hpp中声明并定义下面的函数接口:

SketchContainer& getSketch()
      {
          return sketchContainer1;   //获取绘制窗口名字
      }

因为SketchPadView继承于SketchPadViewBase类,所以也具有Base类的成员sketchContainer1。public中声明并定义getSketch()函数,并返回sketchContainer1;其他类(例如SketchPadPresenter)如果拥有SketchPadView类的参数,则可以通过调用getSketch()函数来获取sketchContainer1,并调用SketchContainer.hpp中声明的函数;


SketchPadPresenter

SketchPadPresenter主要提供接口给按钮和滑动控件,实现了对颜色设置、清屏等效果的封装,在SketchPadViewBase文件的交互设计中,通过presenter -> <函数名>进行调用。

SketchPadView.hpp

#ifndef SKETCHPADPRESENTER_HPP
#define SKETCHPADPRESENTER_HPP

#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>

using namespace touchgfx;

class SketchPadView;

class SketchPadPresenter : public touchgfx::Presenter, public ModelListener
{
public:
    SketchPadPresenter(SketchPadView& v);
    virtual void activate();
    virtual void deactivate();

    virtual ~SketchPadPresenter() {}
    //使用Container中提供的清屏和设置颜色的接口
    void clearSketch();
    void setSketchColor(touchgfx::colortype c);
   //用于slider滑动事件的响应
    void updateRedValue(int value);
    void updateGreenValue(int value);
    void updateBlueValue(int value); 
    //用于modalWindow中的按钮
    touchgfx::colortype getColorValue(); //得到实时的r,g,b的颜色,用于调色盘按钮颜色的实时变化
    touchgfx::colortype confirmColorValue(); //提交修改完的颜色

private:
    SketchPadView& view;
    SketchPadPresenter();
    int r,g,b;  //用于临时存储r,g,b的数据,用于调色盘中到画笔颜色的更新
};

#endif // SKETCHPADPRESENTER_HPP

SketchPadView.cpp

#include <gui/sketchpad_screen/SketchPadView.hpp>
#include <gui/sketchpad_screen/SketchPadPresenter.hpp>
#include <touchgfx/Color.hpp>

/**
 * @brief 构造函数,保存 View 引用并初始化 RGB 分量
 *
 * @param v 当前屏幕对应的 SketchPadView 引用
 */
SketchPadPresenter::SketchPadPresenter(SketchPadView& v)
    : view(v),
      r(0),
      g(0),
      b(0)
{
}

/**
 * @brief 当该屏幕切入(变为当前活动屏幕)时自动调用
 *
 * 可以在此处从 Model 中读取状态、初始化颜色等。
 */
void SketchPadPresenter::activate()
{
}

/**
 * @brief 当该屏幕切出(不再是当前活动屏幕)时自动调用
 *
 * 可以在此处将必要状态写回 Model 或做资源释放。
 */
void SketchPadPresenter::deactivate()
{
}

/**
 * @brief 清空绘图画布
 *
 * 通过 View 获取内部的 SketchContainer,并调用其 clear()。
 */
void SketchPadPresenter::clearSketch()
{
    view.getSketch().clear();
}

/**
 * @brief 设置画布的当前画笔颜色
 *
 * @param c 要设置的 RGB565 颜色
 *
 * Presenter 不直接操作容器,而是通过 View 转发到 SketchContainer。
 */
void SketchPadPresenter::setSketchColor(touchgfx::colortype c)
{
    view.getSketch().setColor(c);
}

/**
 * @brief 更新当前颜色的 R 分量
 *
 * @param value 0~255 的红色分量值,对应调色板 R Slider
 */
void SketchPadPresenter::updateRedValue(int value)
{
    r = value;
}

/**
 * @brief 更新当前颜色的 G 分量
 *
 * @param value 0~255 的绿色分量值,对应调色板 G Slider
 */
void SketchPadPresenter::updateGreenValue(int value)
{
    g = value;
}

/**
 * @brief 更新当前颜色的 B 分量
 *
 * @param value 0~255 的蓝色分量值,对应调色板 B Slider
 */
void SketchPadPresenter::updateBlueValue(int value)
{
    b = value;
}

/**
 * @brief 根据当前 RGB 分量组合出颜色,但不立即应用到画布
 *
 * @return 由 r/g/b 组合得到的 RGB565 颜色值
 *
 * 通常用于在调色板中“预览”颜色,例如更新 OK 按钮文本颜色。
 */
touchgfx::colortype SketchPadPresenter::getColorValue()
{
    touchgfx::colortype c = touchgfx::Color::getColorFromRGB(r, g, b);
    return c;
}

/**
 * @brief 确认当前颜色并应用到画布
 *
 * @return 实际应用到 SketchContainer 的 RGB565 颜色值
 *
 * 一般在 ColorSetModalWindow 的 OK 按钮点击时调用:
 * - 先由 View 把 Slider 的最终值写入 r/g/b
 * - 调用本函数生成颜色并设置给 SketchContainer
 */
touchgfx::colortype SketchPadPresenter::confirmColorValue()
{
    touchgfx::colortype c = touchgfx::Color::getColorFromRGB(r, g, b);
    setSketchColor(c);   // 真正把颜色传给容器
    return c;
}

TouchGFX设计交互

完成上面部分的内容后,我们回到TouchGFX Designer添加控件的交互内容。此处内容重复性比较强,只展示具有代表性的:


和ModalWindow显示有关的交互

首先是首次进入画面,即Screen Transition begins,应当隐藏ModalWindow; image.png

然后是调色盘按钮ColorChooseBtn按下时,展示ModalWindow; image.png

最后是点击确认按钮ColorConfirmBtn时,隐藏ModalWindow。 image.png


颜色按钮部分

颜色按钮都只需要在点击时调用presenter中的setSketchColor()函数: presenter->setSketchColor(touchgfx::Color::getColorFromRGB(255,10,10));

这行代码设置的是红色,其他颜色只需要将调节得到的色彩值填入括号中即可。

image.png

image.png


清屏按钮

实现清屏只需要调用presenter中的clearSketch()函数:

presenter->clearSketch(); image.png


滑块颜色的更新和显示

滑块的回调函数包含有一个int类型的value,是根据滑块位置映射的数值,范围是我们之前设置的0~255。在滑块的交互设置中将这个参数传递给presenter并存储,即presenter->updateRedValue(value); 则传递给了presenter的 r(或g,b)私有变量。

接着是将value传给文本通配符的缓冲区,使用snprintf函数实现;最后使用invalidate()宣告当前区域无效,需要刷新显示。

Unicode::snprintf(RedValueBuffer, REDVALUE_SIZE, "%d", value);
RedValue.invalidate();

然后为了方便预览颜色效果,我们决定用ColorConfirmBtn展示颜色,需要将按钮的 Box With Border 元素颜色实时地设置为三个滑块表示的颜色,当前颜色使用前面定义的 presenter->getColorValue() 接口获取,返回的是一个 touchgfx::colortype 类型的值;

通过setBoxWithBorderColors()设置按钮颜色:setBoxWithBorderColors()的四个参数,第一个参数是松开状态按钮的颜色,其他三个参数分别是按钮按下、边框松开、边框按下的颜色,任意给一个数值即可;

ColorConfirmBtn.setBoxWithBorderColors(presenter->getColorValue(), touchgfx::Color::getColorFromRGB(50, 50, 50), touchgfx::Color::getColorFromRGB(0, 51, 102), touchgfx::Color::getColorFromRGB(4, 49, 94));

ColorConfirmBtn.invalidate();

完整代码如下:

//Red
presenter->updateRedValue(value);
Unicode::snprintf(RedValueBuffer, REDVALUE_SIZE, "%d", value);
RedValue.invalidate();
ColorConfirmBtn.setBoxWithBorderColors(presenter->getColorValue(), touchgfx::Color::getColorFromRGB(50, 50, 50), touchgfx::Color::getColorFromRGB(0, 51, 102), touchgfx::Color::getColorFromRGB(4, 49, 94));
ColorConfirmBtn.invalidate();

同样的,BlueSlider和GreenSlider的回调函数中也应该加入类似代码:

//Blue
presenter->updateBlueValue(value);
Unicode::snprintf(BlueValueBuffer, BLUEVALUE_SIZE, "%d", value);
BlueValue.invalidate();
ColorConfirmBtn.setBoxWithBorderColors(presenter->getColorValue(), touchgfx::Color::getColorFromRGB(50, 50, 50), touchgfx::Color::getColorFromRGB(0, 51, 102), touchgfx::Color::getColorFromRGB(4, 49, 94));
ColorConfirmBtn.invalidate();
//Green
presenter->updateGreenValue(value);
Unicode::snprintf(GreenValueBuffer, GREENVALUE_SIZE, "%d", value);
GreenValue.invalidate();
ColorConfirmBtn.setBoxWithBorderColors(presenter->getColorValue(), presenter->getColorValue(), presenter->getColorValue(), touchgfx::Color::getColorFromRGB(4, 49, 94));
ColorConfirmBtn.invalidate();

image.png


调色盘中的确认按钮

最后是确认按钮的点击事件,除了前面已经添加的隐藏ModalWindow的交互,还需要将颜色上传给SketchContainer中的currentColor,颜色设置才算完成。为了方便在绘制时查看颜色,我们也可以改变调色盘唤出按钮的颜色,即ColorChooseBtn的颜色。

使用presenter->confirmColorValue()将presenter的三个私有变量r, g, b上传为SketchContainer的画笔颜色;

因为confirmColorValue()的返回值是 touchgfx::colortype 类型,所以可以直接放到setBoxWithBorderColors中作为参数。

ColorChooseBtn.setBoxWithBorderColors(presenter->confirmColorValue(), touchgfx::Color::getColorFromRGB(0, 50, 66), touchgfx::Color::getColorFromRGB(84, 84, 84), touchgfx::Color::getColorFromRGB(4, 49, 94));

image.png

效果展示

至此所有的交互都已经编写完成,下载到板上看看效果。

13409218105889068.gif

工程源文件已经放在Github上:STM32F429-TouchGFX/MyApplication_SketchPad at main · Chiando-1100/STM32F429-TouchGFX

image.png
收藏 评论0 发布时间:2025-12-3 15:29

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版