软件环境:STM32CubeMX5.3 、TouchGFX 4.10.0 Designer、uVision5.28.0.0
硬件环境:正点原子阿波罗STM32F767开发板、4.3寸LCD接口屏(480×272)
源码链接: https://github.com/ningjw/stm32f7_os/tree/bb1ae5387d1188141e9f6d582fd5c51dcb8fb02e
在进行触摸屏界面设计时,对话框与虚拟键盘是最常用的,本篇主要就将如何通过自定义 容器实现这两种功能。
最终效果图如下所示:
1. 打开TouchGFX软件,单击Custom Container下的“+”号,添加自定义容器,命名为ContainerDialog
2. 往你刚刚新建的容器中添加控件,下面这个对话框由Image + Text Area + 两个Button组成,设计完界面后就可以点击“Generate Code”按钮生成代码了。打开KEIL工程,可以发现在Application/User/TouchGFX/generated文件夹下有containerdialogbase.cpp文件,该文件实现了对下方对话框的界面设计。
3. 接下来才是重点,通过代码的方式为上述两个按钮设置单击事件。
我们设计出该对话框后是要在多处使用的,在不同的场景下呈现的文字可能不一样,同时单击OK按钮与Cancel可能需要进行不同的处理(即多态性)。下面开始进行代码修改:
打开containerdialog.hpp文件,声明一个共有的联合体(联合体具有两个成员,一个表示OK按钮按下,一个表示Cancel按钮按下),两个共有函数,一个是设置显示的文本,一个是用于设置按钮回调函数
public:
typedef enum { OK, CANCEL } Answer;
void setText(touchgfx::TypedTextId textId);
void setAnsweredCallback(touchgfx::GenericCallback<Answer>& callback);
在protected下添加如下函数与变量
定义一个touchgfx::GenericCallback<Answer>* 类型的指针,该指针最终指向Ok与Cancel的回调函数。
定义一个touchgfx::Callback<ContainerDialog, const touchgfx::AbstractButton&>对象,该对象用于绑定OK与Cancel按钮与buttonClicked函数
protected:
touchgfx::GenericCallback<Answer>* callback;
touchgfx::Callback<ContainerDialog, const touchgfx::AbstractButton&> onButtonClicked;
void buttonClicked(const touchgfx::AbstractButton& btn);
打开containerdialog.cpp函数,修改后的文件如下所示:
#include <gui/containers/ContainerDialog.hpp>
ContainerDialog::ContainerDialog():
onButtonClicked(this, &ContainerDialog::buttonClicked)//绑定回调函数
{
}
void ContainerDialog::initialize()
{
ContainerDialogBase::initialize();
}
//设置显示的文本
void ContainerDialog::setText(touchgfx::TypedTextId textId)
{
textArea1.setTypedText(touchgfx::TypedText(textId));
textArea1.setPosition(0, 50, 240, textArea1.getTextHeight());
invalidate();
}
//设置回调函数
void ContainerDialog::setAnsweredCallback(touchgfx::GenericCallback<Answer>& callback)
{
this->callback = &callback;
}
//当按钮按下时,会调用该函数
void ContainerDialog::buttonClicked(const touchgfx::AbstractButton& btn)
{
//--------------------------------------
// 您也可以在次数添加一些处理
//--------------------------------------
if (callback && callback->isValid())//判断回调函数是否为空
{
//调用设置的回调函数
callback->execute(&btn == &buttonOk ? ContainerDialog::OK : ContainerDialog::CANCEL);
}
}
4 自定义对话框已经完成,接下来使用该对话框
打开Screen1View.hpp,进行如下修改:
添加头文件:
#include <gui/containers/ContainerDialog.hpp>
protected属性下添加:
protected:
ContainerDialog containerDialog;
Callback<Screen1View, ContainerDialog::Answer> onDialogAnswered;
void dialogAnswered(ContainerDialog::Answer answer);
打开Screen1View.cpp,进行如下修改,这里就只贴修改的部分了:
Screen1View::Screen1View():
onDialogAnswered(this, &Screen1View::dialogAnswered)
{
}
void Screen1View::setupScreen()
{
// 在创建该屏幕的时候,显示对话框
containerDialog.setXY(HAL::DISPLAY_WIDTH / 2 - containerDialog.getWidth() / 2, HAL::DISPLAY_HEIGHT / 2 - containerDialog.getHeight() / 2);
containerDialog.setText(T_DIALOGMSG);
containerDialog.setAnsweredCallback(onDialogAnswered);
add(containerDialog);
}
//当从对话框退出时,会调用该回调函数,参数指示了是点击了OK按钮还是Cancel按钮
void Screen1View::modalAnswered(ModalDialog::Answer answer)
{
containerDialog.setVisible(false);
containerDialog.invalidate();
}
总结:
本文的重点是学会使用回调函数实现对话框的多态性。学会了该知识点,要实现键盘就简单不少了,只是界面布局不一样,然后按钮多点。
当然我们如果仔细看官方手册的话,会发现有一个ModalWindow类(对应TouchGFX 的ModalWindow空间),使用该类可以非常简单的实现对话框功能;
同时也有一个Keyboard类,专门用于实现键盘功能,这个看官方的例子就行了。