教程4:创建具有自定义行为的滚轮。
在本教程中,您将学习如何创建和配置两个控件 - 自定义容器和滚轮。 自定义容器控件使用户能够通过组合多个其他控件来创建新的控件,并为自定义容器中的控件添加特定行为。 滚轮是用来创建可滚动菜单的控件,菜单由多个可选项组成。 本教程将展示如何创建用户代码以便修改控件的行为。
这次我们将使用较大的屏幕,因此用800 x 480像素的分辨率为板卡启动新项目(如STM32F469探索套件),或者也可以直接使用模拟器。
关于自定义容器和滚轮的更多信息,可以在“自定义容器”和“滚轮”页面上找到。
本教程使用的图形可从此链接下载。 将资源下的images文件夹中的文件解压缩,就本教程中使用的项目而言,路径为MyApplication2\assets\images。
第1步:创建自定义容器
与教程2中的第1步类似,首先用TouchGFX Designer新建项目。 这一次,当新项目就绪时,在TouchGFX Designer中从“屏幕”选项卡切换到“容器”选项卡 (1)。
用于创建自定义容器的选项卡与“屏幕”选项卡类似,以与新建屏幕相同的方式新建自定义容器。 在创建自定义容器后,可以为其添加控件,并且可以修改自定义容器的大小和名称。
在“自定义容器”选项卡上,使用“+”按钮 (1) 新建一个自定义容器,将其重命名为“MenuElement”(2),并将宽度修改为390、高度修改为70 (3)。
将控件添加到自定义容器
在创建自定义容器并设置其属性后,可以将控件添加到自定义容器。 本教程中的自定义容器将包含一张图像和一个使用通配符的文本区:
Further reading
按照以下方式插入两个控件:
控件 | 属性 |
---|---|
图像 |
|
TextArea |
|
将自定义容器添加到屏幕
回到“屏幕”选项卡,现在可以在自定义容器下的控件菜单中选择“MenuElement”(1)。 放置一个黑色方块作为背景,并将创建的几个自定义容器添加到画布上。 请注意,您可以在屏幕上自由地移动插入的容器。 自定义容器将显示为左侧“控件”列表中的一个元素 (2)。
第2步:创建滚轮
在教程4的这一步中,我们将使用第1步中创建的自定义容器“MenuElement”创建滚轮。 如第1步中所述,滚轮用于创建包含多个可选项的可滚动菜单。 在滚动时,滚轮中的选项会自动更新;当选中一个选项时,该选项会突出显示。
通过选择要用作“选项模板”的自定义容器,将选项添加到滚轮。 “选项模板”的理念是使用自定义容器中的控件作为滚轮中选项的基础,并在运行时间使用用户代码更新选项中的控件。
创建滚轮
在创建滚轮前,删除屏幕上已插入的自定义容器,仅留下黑色方块作为背景。 在“容器”区下的控件菜单中选择“滚轮”(1)。 创建一个滚轮,将位置属性设置为X = 208、Y = 45和H = 390,并将名称修改为“scrollWheel”。
将选项添加到滚轮
使用滚轮属性“选项模板”下的下拉列表,选择第1步中创建的“MenuElement”作为“选项模板”(1)。 滚轮中的选项数也在“选项模板”下设置。 将其设置为20项。 由于滚轮会突出显示选中项,因此通过设置属性“列表外观”下的“选中项偏移量”(2) 来设置选中项在UI上的位置。 我们希望选中项位于滚轮的中间,因此将“选中项偏移量”设置为 (390-70)/2 = 160。
为了突出显示“scrollWheel”的区域,使用第1步中下载的.zip文件中的两张图像background.png和overlay.png,并将它们作为图像控件添加到应用。 两张图像是背景,突出显示“scrollWheel”的区域和一个覆盖层,后者会在移动到“scrollWheel”的边缘时隐藏“scrollWheel”中的选项。
图像background.png的坐标为X = 205和Y = 45,位于“scrollWheel”后方,因此在背景上方绘制“scrollWheel”中的选项。 overlay.png的坐标为X = 0和Y = 0,位于“scrollWheel”上方,这意味着在overlay.png下方绘制选项,以便隐藏overlay.png不透明部分的选项。
按下CTRL-B和CTRL-F键可以前后移动“控件”列表中的控件。
我们只调整了“scrollWheel”的静态属性,尚未为其添加逻辑。 因此,运行应用将得到一个可滚动菜单,其中包含的20个选项外观全部相同。 在下一步中,我们将用用户代码为“scrollWheel”添加逻辑,以便在运行时间更新滚轮中的选项。
第3步:将用户代码添加到滚轮
我们已在TouchGFX Designer中创建并配置了滚轮“scrollWheel”,这一步将通过用户代码创建逻辑,逻辑更新“scrollWheel”中的选项,以便基于滚轮中选项的位置显示不同图形。 因此,这一步将整合TouchGFX Designer生成的代码和用户代码。 关于整合TouchGFX Designer生成的代码和用户代码的详细说明,可以在“代码结构”页面上找到。
更改MenuElement中的图像和文本
由于滚轮中的选项基于第1步中创建的自定义容器“MenuElement”,因此需将用于更改图标和更新通配符的用户代码添加到“MenuElement”。 如果自定义容器是在TouchGFX 设计器中创建的,将生成与自定义容器同名的.hpp和.cpp文件。 应在这些文件中整合用户代码。 应用示例中为“MenuElement”生成的文件的位置如下:
MyApplication2\gui\include\gui\containers\MenuElement.hpp
MyApplication2\gui\src\containers\MenuElement.cpp
通过将函数setNumber(int no)
添加到“MenuElement”,可以更改“scrollWheel”中选项的文本和图标。 该函数使用变化的编号
来决定应显示哪个图标和图像控件,并将TextArea控件中的通配符更改为编号
值。
由于我们在TextArea中使用了数字0-9,因此还需要将范围“0-9”添加到“默认”字体排印的“通配符范围”。
按下F4键获取TouchGFX Designer生成的文件。
setNumber(int no)
的声明和实现是在MenuElement.hpp
中完成的,如下图所示。
TouchGFX/gui/include/gui/containers/MenuElement.hpp
#ifndef MENUELEMENT_HPP
#define MENUELEMENT_HPP
#include <gui_generated/containers/MenuElementBase.hpp>
#include <BitmapDatabase.hpp>
class MenuElement : public MenuElementBase
{
public:
MenuElement();
virtual ~MenuElement() {}
virtual void initialize();
void setNumber(int no)
{
Unicode::itoa(no, textBuffer, TEXT_SIZE, 10);
switch (no % 7)
{
case 0:
icon.setBitmap(Bitmap(BITMAP_ICON00_ID));
break;
case 1:
icon.setBitmap(Bitmap(BITMAP_ICON01_ID));
break;
case 2:
icon.setBitmap(Bitmap(BITMAP_ICON02_ID));
break;
case 3:
icon.setBitmap(Bitmap(BITMAP_ICON03_ID));
break;
case 4:
icon.setBitmap(Bitmap(BITMAP_ICON04_ID));
break;
case 5:
icon.setBitmap(Bitmap(BITMAP_ICON05_ID));
break;
case 6:
icon.setBitmap(Bitmap(BITMAP_ICON06_ID));
break;
}
}
protected:
};
#endif // MENUELEMENT_HPP
代码使用BITMAP定义来引用项目中的图像。 为了能够使用这些图像,必须像之前一样包含文件“BitmapDatabase.hpp”。
在添加代码更新MenuElement的内容后,下一件要做的事是添加用于更新滚轮中选项的代码。
更新滚轮中的选项
在创建滚轮时,TouchGFX Designer在Screen基类中生成虚拟函数,每当滚轮中的新选项变得可见时都会调用此函数。 在用户代码中重写此函数将使代码能够与滚轮中的选项交互。
函数名称是滚轮名称+UpdatedItem。 就本教程而言,函数名称为scrollWheelUpdateItem(MenuElement& item& int16_t itemIndex)
。
参数itemIndex
是索引值,指示当前正在更新的选项,选项
是对滚轮中当前可见的MenuElement实例的引用。 itemIndex
指示正在更新的选项,为选项调用的setNumber()
将基于itemIndex
的值修改正在更新的选项的内容。 下面是用于更新滚轮选项的代码。
Screen1View.hpp
#ifndef SCREEN1VIEW_HPP
#define SCREEN1VIEW_HPP
#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
class Screen1View : public Screen1ViewBase
{
public:
Screen1View();
virtual ~Screen1View() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void scrollWheelUpdateItem(MenuElement& item, int16_t itemIndex)
{
item.setNumber(itemIndex);
}
protected:
};
#endif // SCREEN1VIEW_HPP
现在运行应用的模拟器,结果显示选项的文本包含其索引值,并且图标随显示的选项而变化。 下图显示了用实现的代码运行模拟器的示例。
第4步:将自定义行为添加到滚轮
在教程4的最后一步中,我们将为滚轮添加自定义行为,使其在滚动选项时以环形模式,即类似于表盘的模式移动。
将自定义行为添加到MenuElement
让滚轮以表盘模式移动,是通过移动滚轮中每个可见选项的图像和文本控件的水平位置来实现的。 为此,在MenuElement.hpp
中重写“MenuElement”
的函数setY()。 每次沿垂直方向移动自定义容器时,都会调用它的setY()
函数,该函数用于在新位置重绘自定义容器。 通过重写setY()
,在每次滚动滚轮时,还能够在容器内部水平移动图像和文本控件。 下图显示了如何在MenuElement.hpp
中实现新的setY(
)函数以及移动两个控件。 请注意,需将math.h
包含在内。
MenuElement.hpp
#ifndef MENUELEMENT_HPP
#define MENUELEMENT_HPP
#include <gui_generated/containers/MenuElementBase.hpp>
#include <BitmapDatabase.hpp>
#include <math.h>
class MenuElement : public MenuElementBase
{
public:
MenuElement();
virtual ~MenuElement() {}
virtual void initialize();
//Adjusts the position of the text and the icon, based in the calculated offset(x)
void offset(int16_t x)
{
icon.setX(30 + x);
text.setX(80 + x);
}
//The new declaration and implementation of the setY() function
virtual void setY(int16_t y)
{
//set Y as normal
MenuElementBase::setY(y);
const int circleRadius = 250;
//center around middle of background
y = y + getHeight() / 2 - 390 /2;
//calculate x
float x_f = circleRadius - sqrtf((float)((circleRadius * circleRadius) - (y * y)));
int16_t x = (int16_t)(x_f + 0.5f);
offset(x);
}
...
实现新的setY()
函数后,运行模拟器,结果显示滚轮以表盘模式(与覆盖层的曲线对齐)移动。
教程4到此结束。