屏幕(Screen)代表一个全屏可绘制区域。应用程序通过继承这个类来创建特定的屏幕。每个屏幕都有一个根容器,可绘制对象会被添加到这个根容器中。屏幕会确保按照正确的顺序将绘制请求和各种事件委托给相应的可绘制对象。
继承关系:
class leadScreen1ViewBase : public touchgfx::View<leadScreen1Presenter>{}
leadScreen1ViewBase 类继承自View类模板
template <class T>
class View : public Screen{}
这是一个用于普通应用程序的通用 TouchGFX 屏幕(touchgfx::Screen)特化版本。它提供了与呈现器(Presenter)类的链接
View类继承自Screen类,Screen类的定义如下:
(1)Screen.hpp
#ifndef TOUCHGFX_SCREEN_HPP
#define TOUCHGFX_SCREEN_HPP
#include <touchgfx/containers/Container.hpp>
#include <touchgfx/events/ClickEvent.hpp>
#include <touchgfx/events/DragEvent.hpp>
#include <touchgfx/events/GestureEvent.hpp>
#include <touchgfx/hal/HAL.hpp>
#include <touchgfx/hal/Types.hpp>
namespace touchgfx
{
class Drawable;
class Transition;
//屏幕(Screen)代表一个全屏可绘制区域。应用程序通过继承这个类来创建特定的屏幕。
//每个屏幕都有一个根容器,可绘制对象会被添加//到这个根容器中。屏幕会确保按照正确的
//顺序将绘制请求和各种事件委托给相应的可绘制对象。
class Screen
{
public:
Screen();
virtual ~Screen()
{
}
void draw();
//启动一次 JSMOC 运行,分析哪些小部件(控件)的哪些部分需要重绘。
//@param [in] invalidatedArea 要重绘的区域,以绝对坐标表示。
void startSMOC(const Rect& invalidatedArea);
//递归JSMOC函数。这是实际的遮挡剔除实现
void JSMOC(const Rect& invalidatedArea, Drawable* widgetToDraw);
//通知屏幕绘制指定区域。将按照 z 轴顺序遍历可绘制对象树,并将绘制操作委托给它们。
virtual void draw(Rect& rect);
//当这个屏幕即将被显示时,由 Application::switchScreen() 函数调用此函数。
//基类版本的该函数不执行任何操作,但请在重写的版本中放置任何特定于该屏幕的初始化代码。
virtual void setupScreen()
{
}
//当向该屏幕的过渡完成时,由 Application::handleTickEvent() 调用此函数。
//基类版本的此函数不执行任何操作,但你可以重写它,以编写在屏幕过渡完成后
//必须执行的特定于该屏幕的初始化代码。
virtual void afterTransition()
{
}
//当这个屏幕将不再显示时,由 Application::switchScreen() 调用此函数。
//基类版本的该函数不执行任何操作,但请在重写的版本中放置任何特定于该屏幕的清理代码。
virtual void tearDownScreen()
{
}
//以相反的z顺序遍历绘图,并通知他们点击事件
virtual void handleClickEvent(const ClickEvent& event);
//以相反的z顺序遍历可绘制对象,并通知它们拖动事件
virtual void handleDragEvent(const DragEvent& event);
//处理手势。以反向z遍历可绘制对象并通知它们该手势
virtual void handleGestureEvent(const GestureEvent& event);
//由当前屏幕上的应用程序调用,频率为TICK_INTERVAL_MS
virtual void handleTickEvent()
{
}
//当应用程序接收到一个 “按键” 信号时会调用此函数,该 “按键” 的具体含义取决于平台和应用程序本身。
//默认实现不执行任何操作。
virtual void handleKeyEvent(uint8_t key)
{
(void)key; // Unused variable
}
//确定是否使用JSMOC。
bool usingSMOC() const
{
return useSMOC;
}
//启用访问容器的转换,启用(允许)过渡操作以访问容器。
void bindTransition(Transition& trans);
//获取此屏幕根容器的引用。
Container& getRootContainer()
{
return container;
}
//获取当前屏幕的宽度。在大多数情况下,这个宽度与 HAL::DISPLAY_WIDTH 的值相同。
int16_t getScreenWidth() const
{
return HAL::DISPLAY_WIDTH;
}
//获取当前屏幕的高度。在大多数情况下,该高度与 HAL::DISPLAY_HEIGHT 的值相同。
int16_t getScreenHeight() const
{
return HAL::DISPLAY_HEIGHT;
}
protected:
//确定是使用 JSMOC 算法还是画家算法进行绘制。
void useSMOCDrawing(bool enabled);
//将可绘制内容添加到内容容器中
//绝对不能对已经添加到屏幕上的可绘制对象(Drawable)调用此函数。
//如果不确定(该可绘制对象是否已添加到屏幕),请先调用 remove() 函数。
void add(Drawable& d)
{
container.add(d);
}
//在特定子节点之后插入一个可绘制对象。请参考 Container::insert 方法。
//这段注释描述了一个插入可绘制对象(Drawable)的方法。其核心功能是将一个新的
//可绘制对象插入到指定的另一个可绘制对象之后,若指定的可绘制对象为 null,则将新对象作为头部插入。
void insert(Drawable* previous, Drawable& d)
{
container.insert(previous, d);
}
//其主要目的是在图形界面中,当某个区域的显示内容需要更新时,通知系统对该区域进行重绘,
//以保证界面显示的正确性和实时性。
void invalidateRect(Rect& invalidatedArea) const
{
container.invalidateRect(invalidatedArea);
}
//告知框架整个屏幕都需要重绘
void invalidate() const
{
container.invalidate();
}
//从内容容器中移除一个可绘制对象。即使该可绘制对象从未被添加过,
//调用此方法也是安全的(在这种情况下,不会发生任何操作)
void remove(Drawable& d)
{
container.remove(d);
}
//这个容器包含了屏幕的内容。
Container container; ///< The container contains the contents of the screen.
//当前获得焦点的可绘制对象(在接收到 DOWN_PRESSED 事件时设置)。
Drawable* focus; ///< The drawable currently in focus (set when DOWN_PRESSED is received).
private:
int16_t fingerAdjustmentX;
int16_t fingerAdjustmentY;
bool useSMOC;
};
} // namespace touchgfx
#endif // TOUCHGFX_SCREEN_HPP
(2)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 afterTransition();
virtual void handleTickEvent();
virtual void printButtonClickHandler();
virtual void handleClickEvent(const ClickEvent & event);
virtual void handleDragEvent(const DragEvent & event);
virtual void handleGestureEvent(const GestureEvent & event);
virtual void handleKeyEvent(uint8_t key);
protected:
};
#endif // SCREEN1VIEW_HPP
(3)Screen1View.cpp
#include <gui/screen1_screen/Screen1View.hpp>
#ifndef SIMULATOR
#include "key.h"
#else
#define KEY0_PRES '0'
#define KEY1_PRES '1'
#endif
uint8_t age2 = 0;
Screen1View::Screen1View()
{
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
//代表我们当前的屏幕界面已经处于就绪状态了
void Screen1View::afterTransition()
{
touchgfx_printf("afterTransition\r\n");
}
//每隔一定的周期被系统给调用 20ms左右
void Screen1View::handleTickEvent()
{
static uint8_t tick = 0;
tick++;
if(tick==50)
{
tick = 0;
//touchgfx_printf("handleTickEvent\r\n");
}
}
//printButton的点击事件
void Screen1View::printButtonClickHandler()
{
//写法1
// uint8_t age = presenter->getModel()->getAge()+1;
// presenter->getModel()->setAge(age);
//写法2
presenter->setAge(presenter->getAge()+1);
//全局变量方式传参
age2++;
touchgfx_printf("printButton\r\n");
}
//重写点击事件
void Screen1View::handleClickEvent(const ClickEvent & event)
{
Screen1ViewBase::handleClickEvent(event);//特别注意这里
ClickEvent::ClickEventType type = event.getType();
if(type==ClickEvent::PRESSED)
{
touchgfx_printf("handleClickEvent PRESSED\r\n");
image1.setXY(event.getX(),event.getY());
//image1.invalidate();
getRootContainer().invalidate();
}else if(type==ClickEvent::RELEASED)
{
touchgfx_printf("handleClickEvent RELEASED\r\n");
}else if(type==ClickEvent::CANCEL)
{
//touchgfx_printf();函数的头文件为:#include <touchgfx/Utils.hpp>
touchgfx_printf("handleClickEvent CANCEL\r\n");
}
}
//重写屏幕的拖拽事件,相当于Move事件
void Screen1View::handleDragEvent(const DragEvent & event)
{
Screen1ViewBase::handleDragEvent(event);
if(event.getType()==DragEvent::DRAGGED)
{
touchgfx_printf("handleDragEvent x:%d y:%d delta_x:%d delta_y:%d old_x:%d old_y:%d\r\n",
event.getNewX(),event.getNewY(),event.getDeltaX(),event.getDeltaY(),event.getOldX(),event.getOldY()
);
image1.setXY(event.getNewX(),event.getNewY());
getRootContainer().invalidate();
}
}
void Screen1View::handleGestureEvent(const GestureEvent & event)
{
// GestureEvent::GestureEventType type = event.getType();
// if(type==GestureEvent::SWIPE_HORIZONTAL)
// {
// }else if(type==GestureEvent::SWIPE_VERTICAL)
// {
// }
touchgfx_printf("handleGestureEvent x:%d y:%d speed:%d dir:%d\r\n",
event.getX(),event.getY(),event.getVelocity(),event.getType()
);
}
void Screen1View::handleKeyEvent(uint8_t key)
{
if(key==KEY0_PRES)
{
touchgfx_printf("handleKeyEvent KEY0_PRES\r\n");
image1.setVisible(false);
image1.invalidate();
}else if(key==KEY1_PRES)
{
touchgfx_printf("handleKeyEvent KEY1_PRES\r\n");
image1.setVisible(true);
image1.invalidate();
}
}
//1.遵循touchgfx的MVP架构的model方式
//2.全局变量方式
//3.freeRTOS的邮箱,信号量等
(一)传递参数机制:遵循touchgfx的MVP架构的model方式
(1)在Model.hpp中定义成员变量uint8_t age;
#ifndef MODEL_HPP
#define MODEL_HPP
#include <touchgfx/hal/Types.hpp>
class ModelListener;
class Model
{
public:
Model();
void bind(ModelListener* listener)
{
modelListener = listener;
}
void tick();
void setAge(uint8_t age);
uint8_t getAge();
protected:
ModelListener* modelListener;
uint8_t age;
};
#endif // MODEL_HPP
(2)在Model.cpp中初始化成员变量uint8_t age;
#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>
//冒号后面是构造函数初始化列表,初始化私有成员变量modelListener
//因为ModelListener*不是基础数据类型,所以必须再次初始化
Model::Model() : modelListener(0)
{
//基础数据类型可以在这里初始化
age = 0;
}
void Model::tick()
{
}
void Model::setAge(uint8_t age)
{
this->age = age;
}
uint8_t Model::getAge()
{
return age;
}
(3)改写Screen1Presenter.hpp
#ifndef SCREEN1PRESENTER_HPP
#define SCREEN1PRESENTER_HPP
#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>
using namespace touchgfx;
class Screen1View;
class Screen1Presenter : public touchgfx::Presenter, public ModelListener
{
public:
Screen1Presenter(Screen1View& v);
virtual void activate();
virtual void deactivate();
virtual ~Screen1Presenter() {};
Model * getModel();
void setAge(uint8_t age);
uint8_t getAge();
private:
Screen1Presenter();
Screen1View& view;
};
#endif // SCREEN1PRESENTER_HPP
(4)改写Screen1Presenter.cpp
#include <gui/screen1_screen/Screen1View.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
Screen1Presenter::Screen1Presenter(Screen1View& v)
: view(v)
{
}
void Screen1Presenter::activate()
{
}
void Screen1Presenter::deactivate()
{
}
Model * Screen1Presenter::getModel()
{
return model;
}
void Screen1Presenter::setAge(uint8_t age)
{
model->setAge(age);
}
uint8_t Screen1Presenter::getAge()
{
return model->getAge();
}
(5) 在屏幕Screen1View.cpp上就可以使用presenter->getModel()->getAge()+1;
//printButton的点击事件
void Screen1View::printButtonClickHandler()
{
//写法1
uint8_t age = presenter->getModel()->getAge()+1;
presenter->getModel()->setAge(age);
//写法2
presenter->setAge(presenter->getAge()+1);
//全局变量方式传参
age2++;
touchgfx_printf("printButton\r\n");
}
(6)改写界面2的相关文件,Screen2View.hpp
#ifndef SCREEN2VIEW_HPP
#define SCREEN2VIEW_HPP
#include <gui_generated/screen2_screen/Screen2ViewBase.hpp>
#include <gui/screen2_screen/Screen2Presenter.hpp>
class Screen2View : public Screen2ViewBase
{
public:
Screen2View();
virtual ~Screen2View() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void afterTransition();
protected:
};
#endif // SCREEN2VIEW_HPP
(7)改写界面2的相关文件,Screen2View.cpp
#include <gui/screen2_screen/Screen2View.hpp>
#include <touchgfx/Unicode.hpp>
extern uint8_t age2;
Screen2View::Screen2View()
{
}
void Screen2View::setupScreen()
{
Screen2ViewBase::setupScreen();
}
void Screen2View::tearDownScreen()
{
Screen2ViewBase::tearDownScreen();
}
void Screen2View::afterTransition()
{
//MVP方式
uint8_t age = presenter->getAge();
Unicode::snprintf(textArea1Buffer,TEXTAREA1_SIZE,"age:%d",age);
textArea1.invalidate();
//全局变量的方式
// Unicode::snprintf(textArea1Buffer,TEXTAREA1_SIZE,"age:%d",age2);
// textArea1.invalidate();
}
(8)改写界面2的相关文件,Screen2Presenter.hpp
#ifndef SCREEN2PRESENTER_HPP
#define SCREEN2PRESENTER_HPP
#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>
using namespace touchgfx;
class Screen2View;
class Screen2Presenter : public touchgfx::Presenter, public ModelListener
{
public:
Screen2Presenter(Screen2View& v);
virtual void activate();
virtual void deactivate();
virtual ~Screen2Presenter() {};
Model * getModel();
void setAge(uint8_t age);
uint8_t getAge();
private:
Screen2Presenter();
Screen2View& view;
};
#endif // SCREEN2PRESENTER_HPP
(8)改写界面2的相关文件,Screen2Presenter.cpp
#include <gui/screen2_screen/Screen2View.hpp>
#include <gui/screen2_screen/Screen2Presenter.hpp>
Screen2Presenter::Screen2Presenter(Screen2View& v)
: view(v)
{
}
void Screen2Presenter::activate()
{
}
void Screen2Presenter::deactivate()
{
}
Model * Screen2Presenter::getModel()
{
return model;
}
void Screen2Presenter::setAge(uint8_t age)
{
model->setAge(age);
}
uint8_t Screen2Presenter::getAge()
{
return model->getAge();
}