UI系统

一.定义相关的结构体

整体流程和之前都是差不多的,都是抽象出一个表示具体数据的结构体和一个操作这些数据的结构体

表示数据的结构体

typedef struct Region {
	int iLeftUpX;
	int iLeftUpY;
	int iWidth;
	int iHeigh;
}Region, *PRegion;

里面的数据表示这块区域的左上角的坐标和长度和宽度

操作函数的结构体

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;
	ONPRESSED_FUNC OnPressed;
}Button, *PButton;

这里的typedef的作用是定义一个函数的具体格式的数据结构,后续使用这个函数时表明具体的函数的结构就是这种类型的

二.实现步骤

1.初始化某个按钮

void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)
{
	ptButton->status = 0;
	ptButton->name = name;
	ptButton->tRegion = *ptRegion;
	ptButton->OnDraw    = OnDraw ? OnDraw : DefaultOnDraw;
	ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed;
}

2.实现具体函数

将自己想要实现的按钮的一些参数传入表示按钮的结构体

ptButton->OnDraw    = OnDraw ? OnDraw : DefaultOnDraw;

表示可以传入这个按钮的绘制方法,可以自己设置绘制的颜色,形状等,也可以使用默认的绘制方法(底色是红色,形状是长方形),具体方法如下

static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff)
{
	/* 绘制底色 */
	DrawRegion(&ptButton->tRegion, BUTTON_DEFAULT_COLOR);

	/* 居中写文字 */
	DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);

	/* flush to lcd/web */
	FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);

	return 0;
}

绘制底色和居中写文字的实现和之前一样,可以使用矢量字体,或者使用其他字体也可以,因为绘制时获取的地址就是lcd的实际地址而不是虚拟地址,所以刷新函数直接写空,若是绘制到web端则需要具体实现刷新函数

ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed;

同理,表示按下的事件,可以自己设置长按,短按,按下发生的事件等,也可以使用默认的方法,按下底色变为绿色,具体实现方法

static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
	unsigned int dwColor = BUTTON_DEFAULT_COLOR;
	
	ptButton->status = !ptButton->status;
	if (ptButton->status)
		dwColor = BUTTON_PRESSED_COLOR;

	/* 绘制底色 */
	DrawRegion(&ptButton->tRegion, dwColor);

	/* 居中写文字 */
	DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);

	/* flush to lcd/web */
	FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
	return 0;
}

需要先判断是否按下,每次按下按钮将status设置为相反数,再更改绘制的底色的颜色即可

3.整体绘制的代码

	tRegion.iLeftUpX = 200;
	tRegion.iLeftUpY = 200;
	tRegion.iWidth   = 300;
	tRegion.iHeigh   = 100;
	
	InitButton(&tButton, "test", &tRegion, NULL, NULL);
	tButton.OnDraw(&tButton, ptBuffer);
	while (1)
	{
		tButton.OnPressed(&tButton, ptBuffer, NULL);
		sleep(2);
	}

注意:这里并没有实现按下这块区域的输入,所以只会循环交替显示

页面系统

这里需要构建一个操作函数的结构体

typedef struct PageAction {
	char *name;
	void (*Run)(void *pParams);
	struct PageAction *ptNext;
}PageAction, *PPageAction;

里面的pParams参数页面是各种各样的,所以不能像之前一样直接构造出一种表示具体数据的结构体,需要根据自己需要多次构建结构体

实现流程和之前差不多,需要先注册页面,将页面添加到链表,而前面的UI系统不需要注册按钮的原因是可以每个按钮都是处于具体的位置的,按钮之间不需要进行交流,按钮之间是相互独立的,而页面则需要相互切换,所以需要注册

void PageRegister(PPageAction ptPageAction)
{
	ptPageAction->ptNext = g_ptPages;
	g_ptPages = ptPageAction;
}

然后选择出自己所需要的页面

PPageAction Page(char *name)
{
	PPageAction ptTmp = g_ptPages;

	while (ptTmp)
	{
		if (strcmp(name, ptTmp->name) == 0)
			return ptTmp;
		ptTmp = ptTmp->ptNext;
	}

	return NULL;
}

整体代码

	PagesRegister();
	Page("main")->Run(NULL);

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐