1. 引言
TouchGFX 是专用于 STM32 的图形界面设计软件,可用来低成本开发优秀的图形界面,TouchGFX 现已变的越来越流行。为了帮助客户更加深入地理解和使用 TouchGFX ,本文介绍了 TouchGFX Designer 中的 Mixin 功能,从基础示例 Button Example 出发,为文本框控件添加 ClickListener (Mixin 功能中的一项),并对源代码进行简单剖析。期望能帮助客户更深入地理解 STM32 TouchGFX 的相关功能。
2. TouchGFX ClickListener 模板的使用
2.1. C++模板编程基础
在示例介绍之前,让我们先熟悉一下 C++模板编程的一些基础知识。模板编程属于通用编程的范畴,是为“尚未确定类型”所写的函数或类。是可以产生更干净、更快速、更精明的软件的一个强力手段。
模板的优点:首先模板与某种特定类型无关,代码可重用性好;其次模板与平台无关,代码移植性好;另外模板代码在编译时才进行解释,在编译时确定检查数据类型,相比运行时检查,类型的安全性高。
模板的缺点:一是代码易读性不是很好,调试不便;二是用户工程代码中需要包含模板代码(非二进制库),编译的时间较长,二进制扩展性差;另外有可能会造成二进制代码膨胀(编译后二进制代码臃肿),我们在设计模板时,需要尽可能将 C++模板中与参数⽆关的代码分离出来。
2.2. TouchGFX Mixin 功能简介
模板一般分为函数模板和类模板。函数模板我们这里不做赘述,重点关注 TouchGFX Mixins 类模板。TouchGFX 的 Mixins 类模板用于拓展控件的功能,目前 TouchGFX v4.20.0 中有四个 Mixin 功能,分别是 Draggable、ClickListener、FadeAnimator 和MoveAnimator,分别为控件增添相关功能。如图 1 (TouchGFX Designer Mixins 功能)
所示,本文主要针对 ClickListener 做具体介绍。
图1. TouchGFX Designer Mixins 功能
2.3. 基于 TouchGFX Button 例程使用 ClickListener 功能
2.3.1. TouchGFX 例程的代码生成
运行 TouchGFX Designer,选择 Examples;通过 Select Board Setup 选择STM32H735G DK 板;从众多例程中选择“Button Example”例程;将 Application name 改为 Button_Example,如下图图 2,然后点击 Create 创建工程。
图2.TouchGFX Designer 生成 Button Example 例程
进入 TouchGFX Designer 主界面后,会看到画布上有两个按钮和一个文本框,我们对界面不做更改,直接选择 Designer 右下角 (Run Target)生成代码。该操作将会复制TouchGFX 框架文件,生成配置文件、makefile、代码及资源文件(images、fonts、texts),然后编译链接、烧录目标板并运行。程序运行起来后,您可以熟悉一下该按钮例程应用。下面我们就针对该例程,为界面上的计数文本框控件注入 ClickListener 功能,应用实现“当点击计数文本框时,计数数字增加 2”的功能。
2.3.2. 为计数文本框控件添加 ClickListener 功能
我们在 TouchGFX Designer 主屏界面,点击 countTxt 文本框,然后在右侧属性栏中找到 Mixins,勾选 ClickListener,如图 3 所示。然后重新生成代码。
图3.TouchGFX Designer, 计数文本框 mixin ClickListener 功能
我们可以使用 VS code 编辑代码,或使用其它如 STM32CubeIDE 等工具编辑代码。
打开 MainView.hpp,为计数文本框,添加代码如下(黄底色部分):
#ifndef MAIN_VIEW_HPP
#define MAIN_VIEW_HPP
#include <gui_generated/main_screen/MainViewBase.hpp>
#include <gui/main_screen/MainPresenter.hpp>
class MainView : public MainViewBase
{
public:
MainView();
~MainView() {};
virtual void setupScreen();
virtual void increaseValue();
virtual void decreaseValue();
void updateGFXElements();
void cntTextClickHandler(const TextAreaWithOneWildcard& cntTxt, const ClickEvent& e);
protected:
private:
uint8_t count;
Callback<MainView, const TextAreaWithOneWildcard&, const
ClickEvent&> txtClickedCallback;
};
#endif // MAIN_VIEW_HPP
然后我们转到 MainView.cpp 文件,首先将 txtClickedCallback 对象与 MainView的 cntTextClickHandler(文本框点击处理函数)绑定,这是在 MainView 类的构造函数中初始化列表中实现的。将 txtClickedCallback 加入初始化列表中,参数使用指向MainView 中 cntTextClickHandler 函数的函数指针。我们还需要修改 setupScreen 函数,在这里为 countTxt 添加 ClickAction,参数使用 txtClickedCallback, 以实现在主屏界面创建时,将 countTxt 文本框的点击事件与 txtClickedCallback 对象绑定在一起。另外我们还需要实现 cntTextClickHandler,具体代码如下:
#include <gui/main_screen/MainView.hpp>
#include "BitmapDatabase.hpp"
const uint8_t UPPER_LIMIT = 42;
const uint8_t LOWER_LIMIT = 0;
MainView::MainView() : count(0), txtClickedCallback(this,
&MainView::cntTextClickHandler) {}
void MainView::setupScreen()
{
updateGFXElements();
countTxt.setClickAction(txtClickedCallback);
}
void MainView::cntTextClickHandler(const TextAreaWithOneWildcard&
cntTxt, const ClickEvent& e)
{
if (ClickEvent::RELEASED == e.getType())
{
increaseValue();
increaseValue();
}
}
void MainView::increaseValue()
{
count = (count++ > UPPER_LIMIT) ? UPPER_LIMIT : count;
updateGFXElements();
}
……
修改完成后,保存,编译,运行。您将会发现当每次点击 countTxt 文本框时,文本框计数会增加 2。至此,我们已经实现了为文本框控件加入 ClickListener 的功能。大家可以看到,在 TouchGFX 应用中使用 ClickListener 类模板做开发是十分便捷的,代码量也较小。下面我们对代码进一步解读。
2.3.3. ClickListener 模板代码
ClickListener 类模板是 TouchGFX 框架的一部分,封装在 ClickListener.hpp 中,代码如下:
namespace touchgfx
{
/**
* Mix-in class that extends a class with a click action event that
is called when the class
* receives a click event.
* @tparam T specifies the type to extend with the ClickListener
behavior. */
template <class T>
class ClickListener : public T
{
public:
/** Initializes a new instance of the ClickListener class. Make
the object touchable. */
ClickListener() : T(), clickAction(0)
{
T::setTouchable(true);
}
/**
* Ensures that the clickEvent is propagated to the super class T
and to the clickAction listener.
* @param event Information about the click.
*/
virtual void handleClickEvent(const ClickEvent& event)
{
T::handleClickEvent(event);
if (clickAction && clickAction->isValid())
{
clickAction->execute(*this, event);
}
}
/**
* Associates an action to be performed when the class T is
clicked.
* @param callback The callback to be executed. The callback
will be given a reference to T.
*/
void setClickAction(GenericCallback<const T&, const ClickEvent&>& callback)
{
clickAction = &callback;
}
protected:
GenericCallback<const T&, const ClickEvent&>* clickAction; ///< The callback to be executed when T is clicked
};
} // namespace touchgfx
ClickListener 是一个标准的类模板。所谓类模板,就是“包含一个或多个尚未确定类型”的类。必须将具体类型当作模板参数传入,才可使用。当传入模板参数后,该类模板便以你所指定的参数类型,由编译器进行实例化。将具体类型传入到类模板进行实例化,我们会得到一个新的 ClickListener 类,转变为从传入参数(某待定的类)的派生类。
在生成的代码 MainViewBase.hpp 中(MainView 是 MainViewBase 的派生类),我们可以找到 countTxt 的声明:
touchgfx::ClickListener< touchgfx::TextAreaWithOneWildcard > countTxt;这里,该模板示例类是从 TextAreaWithOneWildcard 类(即原计数文本框类型)继承下来的。如果您选择的不是为文本框增加 ClickListener 功能,而是其它控件,则新的ClickListener 实例类将派生自您所用的控件。本例中的继承关系如下:
该 ClickListener 实例类是 TextAreaWithOneWildcard 类的派生类,不仅仅继承了TextAreaWithOneWildcard 的属性与方法,另外还添加了一个 GenericCallback 指针变量clickAction,该指针由附加的 setClickAction 方法赋值。由另一个方法 handleClickEvent使用,在 handleClickEvent 中在响应 Click 事件时,会调用该 clickAction。(关于callback 类的使用,我们这里不做赘述,如果您需要进一步了解,请参考 TouchGFX 相关文档)。
2.3.4. ClickListener 模板应用
我们清楚了 ClickListener 类模板的原理后,回头来看例子中的 ClickListener 的应用代码,就会发现其逻辑十分清晰。
首先在 MainView.hpp 中声明了一个 Callback txtClickedCallback, 和一个事件处理函数 cntTextClickHandler。 在 MainView.cpp 中初始化该 txtClickedCallback, 将其与cntTextClickHandler 关联,即实现当调用该 Callback 时,会转到 cntTextClickHandler 进行处理。
再在 setupScreen 函数中调用 ClickListener 类模板接口 setClickAction 将txtClickedCallback 的地址赋给 ClickListener 实例化类的 clickAction 指针。则ClickListener 实例化类(这里即 TextAreaWithOneWildcard 类的派生类)在处理ClickEvent 时就会执行到 txtClickedCallback 关联的处理函数 cntTextClickHandler最后需要实现 MainView 类中的 Click 事件处理函数 cntTextClickHandler,这里的实现为:当 Click 事件类型为“Click 按键释放”时调用 increaseValue 函数两次。
3. 小结
TouchGFX 是 STM32 专用的界面设计工具,功能强大且易用。本文选择了 Mixins 功能进行简介,从基础示例 Button Example 出发,动手添加 ClickListener (Mixin) 功能,并从源代码的角度浅析了 ClickListener 类模板的使用,助力客户更深入地理解 STM32 TouchGFX。
本文档参考ST官方的《【应用笔记】LAT1206+TouchGFX+控件附加Mixin功能的方法介绍》文档。
参考下载地址:https://download.csdn.net/download/u014319604/88971320