文章目录
- 前言
- 一、UI界面分析
- 二、结构体描述按钮
- 三、按钮初始化
- 四、默认绘制按键事件函数
- 五、默认按下按键事件函数
- 六、测试程序
- 实验效果
- 总结
前言
最近看了 电子量产工具 这个项目,本专栏是对该项目的一个总结。
一、UI界面分析
UI 是用户界面(User Interface)的缩写,指的是人与计算机或其他设备进行交互时所使用的界面。用户界面是用户与系统之间的桥梁,提供了一种方式让用户与计算机进行沟通、操作和获取信息。
用户界面可以包括以下几个方面:
- 图形用户界面(GUI)。
- 命令行界面(CLI)
- 触摸界面
- 声音界面
- 虚拟现实界面(VR)和增强现实界面(AR)
我们的UI系统,就是构造各类GUI元素,比如按钮(目前只实现按钮)。
二、结构体描述按钮
/* 函数指针(绘制按键) */
typedef int (*ONDRAW_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff);
/* 函数指针(按下按钮) */
typedef int (*ONPRESSED_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent);
typedef struct Button {
char *name; // 按键 名字
int status; //按键 按下状态
Region tRegion; // 按键的区域
ONDRAW_FUNC OnDraw; //一个 ONDRAW_FUNC 类型的函数指针,用于指向按钮绘制函数
ONPRESSED_FUNC OnPressed; //一个 ONPRESSED_FUNC 类型的函数指针,用于指向按钮按下事件处理函数
}Button, *PButton;
typedef struct Region { //区域包括 左上角坐标, 高, 宽
int iLeftUpX;
int iLeftUpY;
int iWidth;
int iHeigh;
}Region, *PRegion;
三、按钮初始化
void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)
{
ptButton->status = 0; //初始状态为 0 ,未按下
ptButton->name = name;
ptButton->tRegion = *ptRegion; // 按钮的区域
ptButton->OnDraw = OnDraw ? OnDraw : DefaultOnDraw; //若 OnDraw 为空,则执行默认绘制函数DefaultOnDraw
ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed; //若 OnPressed 为空,则执行默认绘制函数DefaultOnPressed
}
四、默认绘制按键事件函数
绘制各个按钮 Button 的底色,文字,并将其刷新到 DispBuff 上
static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff)
{
/* 绘制底色 */
DrawRegion(&ptButton->tRegion, BUTTON_DEFAULT_COLOR); // 红色 0xff0000
/* 居中写文字 */
DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR); //黑色 0x000000
/* flush to lcd/web */
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
return 0;
}
- 绘制底色
void DrawRegion(PRegion ptRegion, unsigned int dwColor)
{
int x = ptRegion->iLeftUpX;
int y = ptRegion->iLeftUpY;
int width = ptRegion->iWidth;
int heigh = ptRegion->iHeigh;
int i,j;
for (j = y; j < y + heigh; j++)
{
for (i = x; i < x + width; i++)
PutPixel(i, j, dwColor); //描点函数
}
}
- 居中写文字
在 一定的区域 Region,按颜色 dwColor 居中显示名字 name
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor)
{
int n = strlen(name);
int iFontSize = ptRegion->iWidth / n / 2;
FontBitMap tFontBitMap;
int iOriginX, iOriginY;
int i = 0;
int error;
if (iFontSize > ptRegion->iHeigh) //计算字体大小
iFontSize = ptRegion->iHeigh;
/* 当前文字的基点 */
iOriginX = (ptRegion->iWidth - n * iFontSize)/2 + ptRegion->iLeftUpX;
iOriginY = (ptRegion->iHeigh - iFontSize)/2 + iFontSize + ptRegion->iLeftUpY;
SetFontSize(iFontSize); // 设置字体大小
while (name[i]) //字符编码
{
/* get bitmap */
tFontBitMap.iCurOriginX = iOriginX;
tFontBitMap.iCurOriginY = iOriginY;
error = GetFontBitMap(name[i], &tFontBitMap); //根据字符编码获取位图,保存在 参数 tFontBitMap中
if (error)
{
printf("SelectAndInitFont err\n");
return;
}
/* draw on buffer */
DrawFontBitMap(&tFontBitMap, dwColor); // 绘制位图
iOriginX = tFontBitMap.iNextOriginX; //获取下一文字的基点坐标
iOriginY = tFontBitMap.iNextOriginY;
i++;
}
}
- 将绘制到的按钮,刷新到 buffer 上。
返回 LCD 的 framebuffer , 以后上层 APP 可以直接操作LCD, 可以不用 FbFlushRegion
也可以 malloc 返回一块无关的buffer, 要使用 FbFlushRegion。
这里 为了 以后代码的可移植性,加上了刷新界面,但 并未做出任何举动。
五、默认按下按键事件函数
按下按键事件函数 也需要 上面 绘制函数 里的 : 绘制底色, 居中写文字 ,刷新界面。这里就不再 重述了。
static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
unsigned int dwColor = BUTTON_DEFAULT_COLOR; //按钮初始颜色 红色,0xff0000
ptButton->status = !ptButton->status; // 按钮状态,未按下时 为 0
if (ptButton->status)
dwColor = BUTTON_PRESSED_COLOR; //按下的颜色为 绿色, 0x00ff00
/* 绘制底色 */
DrawRegion(&ptButton->tRegion, dwColor);
/* 居中写文字 */
DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);
/* 刷新界面 到 lcd/web */
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
return 0;
}
六、测试程序
- 显示界面初始化
- 字体初始化
- ui 界面
/* 设置按钮的显示位置,宽高 */
tRegion.iLeftUpX = 200;
tRegion.iLeftUpY = 200;
tRegion.iWidth = 300;
tRegion.iHeigh = 100;
/* 显示 "test", 调用默认绘制,按下函数 */
InitButton(&tButton, "test", &tRegion, NULL, NULL);
tButton.OnDraw(&tButton, ptBuffer); //绘制按键
while (1)
{
tButton.OnPressed(&tButton, ptBuffer, NULL); //按下按键,
sleep(2); // 休眠 2 秒
}
实验效果
实验结果就是每隔 2 秒,自动 变换按键的颜色。(我按钮后面的图是 自己的QT界面,忽略即可)
总结
UI 系统界面的逻辑性 不难,就是一些函数的编写有些困难。
这些封装好的代码,可以用于以后代码的一直调用。