【智能水杯托】03-基于TouchGFX的UI设计
[复制链接]
本次作品是设计一款水杯托,能检测水杯使用状态,能够提醒用户及时喝水。初步设计的系统状态机如下图。
图1、状态机
待机状态下,显示一个模拟时钟。如果超过一定时间用户未拿起水杯,进入下一个提醒状态。如果未超时就喝水,进入鼓励状态。
提醒状态下,显示文本“该喝水啦!”。如果用户拿起水杯,进入鼓励状态。
鼓励状态下,显示文本“棒棒哒!”。如果用户放下水杯,进入待机状态。如果超过一定时间用户未放下水杯,进入接水状态。
接水状态下,显示文本“接水去了吗?”。如果用户放下水杯,进入待机状态。
下面开始使用TouchGFX 4.20.0 Designer设计界面。首先基于STM32L496G-DISCO创建一个空工程,如下图。
图2、创建工程
添加背景、控件等等,如下图是添加模拟时钟。
图3、添加控件
经过一番折腾尝试,终于把界面配置好,如下图。由于不熟练,还专门增加一个屏幕,用来测试各个控件的用法。
图4、界面设计
我先在测试屏幕把用到的各个元素进行了一番尝试,并确认代码能实现,然后才向正式的主屏幕移植。如下图是测试屏幕的样子。
图5、测试屏幕
这里特别说明一下,为了模拟水杯拿起和放下,我在主界面设置了两个透明按钮来实现状态的改变。可能有同学会疑惑为啥不用VS实现,这里我特别说明一下,这个平台头次接触,我还没学会(´-﹏-`;)。
下图是其中一个按钮的说明。为了方便按到,我把上半个屏幕作为可触控区域,然后按钮放在最上层,并设置透明。在最右边添加交互,调用一个虚函数。
图6、透明按钮
下图是透明按钮交互虚函数实现的具体介绍,注意有些代码是自动生成的,有些是我添加的。
图7、虚函数实现
然后就是在<MainView.cpp>这个文件中添加代码,实现我设计的状态机。下面是具体的代码。
代码1、状态机实现
#include <gui/main_screen/MainView.hpp>
#include <texts/TextKeysAndLanguages.hpp>
MainView::MainView()
{
tickCounter = 0;
delayCounter = 0;
delayStatus_cur = 0;
position_d = 0;
}
void MainView::setupScreen()
{
MainViewBase::setupScreen();
analogHours = analogClock.getCurrentHour();
analogMinutes = analogClock.getCurrentMinute();
analogSeconds = analogClock.getCurrentSecond();
}
void MainView::tearDownScreen()
{
MainViewBase::tearDownScreen();
}
void MainView::handleTickEvent()
{
tickCounter++;
if (tickCounter % 60 == 0)
{
delayCounter++;
if (++analogSeconds >= 60)
{
analogSeconds = 0;
// delayCounter++;
if (++analogMinutes >= 60)
{
analogMinutes = 0;
if (++analogHours >= 24)
{
analogHours = 0;
}
}
}
// Update the clocks
analogClock.setTime24Hour(analogHours, analogMinutes, analogSeconds);
}
/////////////////////////////////////
#define POS_TIMEOUT 10 //水杯放置时间
#define DRINK_TIMEOUT 5 //拿起水杯喝水时间
#define POS_ON 0 //水杯在位置
#define POS_OFF 1 //水杯离开
switch (delayStatus_cur)
{
case RUN_CLOCK:
if(delayCounter > POS_TIMEOUT)
{
delayStatus_cur = RUN_REMIND;
//隐藏时钟,显示:该喝水啦
//Set textArea1 text to Resource: text_drink
textArea1.setTypedText(touchgfx::TypedText(T_TEXT_DRINK));
textArea1.invalidate();
//Hide analogClock
analogClock.setVisible(false);
analogClock.invalidate();
//Show textArea1
textArea1.setVisible(true);
textArea1.invalidate();
delayCounter = 0;
}
if(position_d == POS_OFF)
{
delayStatus_cur = RUN_GOOD;
//隐藏时钟,显示:棒棒哒
//Set textArea1 text to Resource: T_TEXT_GOOD
textArea1.setTypedText(touchgfx::TypedText(T_TEXT_GOOD));
textArea1.invalidate();
//Hide analogClock
analogClock.setVisible(false);
analogClock.invalidate();
//Show textArea1
textArea1.setVisible(true);
textArea1.invalidate();
delayCounter = 0;
}
break;
case RUN_REMIND:
if(position_d == POS_OFF)
{
delayStatus_cur = RUN_GOOD;
//显示:棒棒哒
//Set textArea1 text to Resource: T_TEXT_GOOD
textArea1.setTypedText(touchgfx::TypedText(T_TEXT_GOOD));
textArea1.invalidate();
}
delayCounter = 0;
break;
case RUN_GOOD:
if(delayCounter > DRINK_TIMEOUT)
{
delayStatus_cur = RUN_REFILL;
//显示:接水去了吗
//Set textArea1 text to Resource: T_TEXT_REST
textArea1.setTypedText(touchgfx::TypedText(T_TEXT_REST));
textArea1.invalidate();
delayCounter = 0;
}
if(position_d == POS_ON)
{
delayStatus_cur = RUN_CLOCK;
//显示时钟,隐藏文字
//Hide textArea1
textArea1.setVisible(false);
textArea1.invalidate();
//Show analogClock
analogClock.setVisible(true);
analogClock.invalidate();
delayCounter = 0;
}
break;
case RUN_REFILL:
if(position_d == POS_ON)
{
delayStatus_cur = RUN_CLOCK;
//显示时钟,隐藏文字
//Hide textArea1
textArea1.setVisible(false);
textArea1.invalidate();
//Show analogClock
analogClock.setVisible(true);
analogClock.invalidate();
}
delayCounter = 0;
break;
default:
break;
}
}
void MainView::updateVal(unsigned int newValue)
{
// position_d = newValue%2;
}
void MainView::functionPosSet()
{
position_d = POS_OFF;
}
void MainView::functionPosCls()
{
position_d = POS_ON;
}
通过使用TouchGFX的仿真功能进行测试除错,确定没问题了就可以一键下载到开发板,在硬件上直接测试了。如下视频为调试好的界面展示。
视频1、界面展示
综上,基础的界面就设计完了。整体看起来可能很简单,但是对于从零开始学习TouchGFX的人,还是要查阅多个例程,构思哪些功能能够用的上,用何种方式配置,以什么形式展示。但是一旦入了门,这个后续用起来就简单了。
后面我开始添加硬件支持,实现实物水杯的拿起、放下检测,和UI配合起来,变成实用的作品。
|