Linux基础项目开发1:量产工具——UI系统(四)

news2024/12/25 9:13:40

前言:

前面我们已经把显示系统、输入系统、文字系统搭建好了,现在我们就要给它实现按钮操作了,也就是搭建UI系统,下面让我们一起实现UI系统的搭建吧

目录

一、按钮数据结构抽象

ui.h

二、按键编程 

1.button.c

 2.disp_manager.c

3. disp_manager.h

三、单元测试

1.ui_test.c

2.unittest下的Makefile

3. ui下的Makefile

4.顶层目录下的Makefile

四、上板测试

1.ubuntu上

2. 开发板上

3.运行效果:


一、按钮数据结构抽象

1.所谓UI,就是User Interface(用户界面),有图像界面(GUI)

2.我们的UI系统,就是构造各类GUI元素,比如按钮(目前只实现按钮)

3.怎么描述一个按钮呢?

        3.1 它的位置、大小怎么表示?

        3.2 怎么绘制它?

        3.3 用户点击它之后,如何处理?

ui.h


#ifndef _UI_H
#define _UI_H

#include <common.h>
#include <disp_manager.h>
#include <input_manager.h>

#define BUTTON_DEFAULT_COLOR 0xff0000
#define BUTTON_PRESSED_COLOR 0x00ff00
#define BUTTON_TEXT_COLOR    0x000000

struct Button;

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;

void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed);

#endif

第9~11行:定义红绿黑三种颜色

第20行:描述结构体的名字

第22行:描述按钮区域的位置

第23行:OnDraw:提供一个绘制函数

第24行:OnPressed:点击以后执行某些函数

二、按键编程 

1.点击按钮后怎么处理,是业务系统的事情

2.所以应该提供一个InitButton函数,让用户可以提供OnPressed函数

3.上层代码通过下面3个函数使用按钮

1.button.c



#include <ui.h>


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;
}

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);

}


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;
}


static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff)

第6~16行:实现默认的 DefaultOnDraw 函数

        第8行:某一区域绘制底色

        第12行:居中写文字

        第15行:刷新到LCD或者web上

static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)

第20~37行:实现默认的 DefaultOnPressed 函数

        第22行:设置初始状态颜色        

        第24行:每次点击初始状态翻转

        第25行:如果初始状态变为1,则颜色进行翻转

        第28~35行:进行颜色变化

void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)

第40~47行:初始化按键

        第42行:记录初始状态

        第43行:将按钮名字传入

        第44行:将按钮所在区域传入

        第45、46行:如果按下一个这个函数存在的话,那就执行这个函数,否则执行默认的函数

 2.disp_manager.c

ptRegion这一部分区域绘制成dwColor的颜色


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);
	}
}

 在一个区域ptRegion中间将位置居中,并且设置字体颜色

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);
		if (error)
		{
			printf("SelectAndInitFont err\n");
			return;
		}

		/* draw on buffer */		
		DrawFontBitMap(&tFontBitMap, dwColor);		

		iOriginX = tFontBitMap.iNextOriginX;
		iOriginY = tFontBitMap.iNextOriginY;	
		i++;
	}
	
}

3. disp_manager.h

#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H

#include <common.h>
#include <font_manager.h>


typedef struct DispBuff {
	int iXres;
	int iYres;
	int iBpp;
	char *buff;
}DispBuff, *PDispBuff;



typedef struct DispOpr {
	char *name;
	int (*DeviceInit)(void);
	int (*DeviceExit)(void);
	int (*GetBuffer)(PDispBuff ptDispBuff);
	int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);
	struct DispOpr *ptNext;
}DispOpr, *PDispOpr;

void RegisterDisplay(PDispOpr ptDispOpr);

void DisplayInit(void);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
int PutPixel(int x, int y, unsigned int dwColor);
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff);
PDispBuff GetDisplayBuffer(void);
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);
void DrawRegion(PRegion ptRegion, unsigned int dwColor);
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor);

#endif




三、单元测试

1.ui_test.c

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>

#include <disp_manager.h>
#include <font_manager.h>
#include <ui.h>

int main(int argc, char **argv)
{
	PDispBuff ptBuffer;
	int error;
	Button tButton;
	Region tRegion;

	if (argc != 2)
	{
		printf("Usage: %s <font_size>\n", argv[0]);
		return -1;
	}
		
	DisplayInit();

	SelectDefaultDisplay("fb");

	InitDefaultDisplay();

	ptBuffer = GetDisplayBuffer();

	FontsRegister();
	
	error = SelectAndInitFont("freetype", argv[1]);
	if (error)
	{
		printf("SelectAndInitFont err\n");
		return -1;
	}

	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);
	}
	
	return 0;	
}

第23~27行:打印用法

        <font_size>指定字库文件

第29~35行:显示系统初始化 

第37~39行:字体系统初始化

第46~57行:UI系统初始化

        第46~49行:显示区域位置

        第51行:初始化按钮  

        第52行:将按钮绘制显示出来

        第55行:模拟点击

2.unittest下的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := 

#obj-y += disp_test.o
#obj-y += input_test.o
#obj-y += font_test.o
obj-y += ui_test.o

3. ui下的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := 

obj-y += button.o

4.顶层目录下的Makefile


CROSS_COMPILE ?= 
AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm

STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump

export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP

CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include

LDFLAGS := -lts -lpthread -lfreetype

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR

TARGET := test


obj-y += display/
obj-y += input/
obj-y += font/
obj-y += ui/
obj-y += unittest/

all : start_recursive_build $(TARGET)
	@echo $(TARGET) has been built!

start_recursive_build:
	make -C ./ -f $(TOPDIR)/Makefile.build

$(TARGET) : built-in.o
	$(CC) -o $(TARGET) built-in.o $(LDFLAGS)

clean:
	rm -f $(shell find -name "*.o")
	rm -f $(TARGET)

distclean:
	rm -f $(shell find -name "*.o")
	rm -f $(shell find -name "*.d")
	rm -f $(TARGET)
	
obj-y += display/
obj-y += input/
obj-y += font/
obj-y += ui/
obj-y += unittest/

四、上板测试

1.ubuntu上

book@100ask:~/source$ make
book@100ask:~/source$ cp -r 20_ui_unittest/ ~/nfs_rootfs/

2. 开发板上

[root@100ask:/]#  mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
[root@100ask:/mnt/20_ui_unittest]# ./test ./simsun.ttc

3.运行效果:

每隔两秒切换一下颜色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1277619.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++作业4

代码整理&#xff0c; 将学过的三种运算符重载&#xff0c;每个至少实现一个运算符的重载 代码&#xff1a; #include <iostream>using namespace std;class Stu {friend const Stu operator*(const Stu &L,const Stu &R);friend bool operator<(const Stu …

软著项目推荐 深度学习疲劳驾驶检测 opencv python

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

【UGUI】Unity为下拉菜单添加选项(DropDown)

要想控制谁就把谁拿到代码里-获取组件-修改组件参数&#xff08;变量或者方法&#xff09; 代码示例&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro;public class UIcontrol : MonoBehavi…

今天给大家分享一套Python入门基础测试题,大家看看都会做吗?

今天给大家分享一套Python入门基础测试题&#xff0c;大家看看都会做吗&#xff1f; 一、测试题 1. 正确下载Anaconda平台或Python安装包并成功安装。 2. 掌握Python注释与print()和input()两个函数的用法&#xff0c;并作答以下选择题&#xff08;不定项选择&#xff0c;正…

【算法】动态规划中的路径问题

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;如果给算法的难度和复杂度排一个排名&#xff0c;那么动态规划算法一定名列前茅。今天&#xff0c;我们通过由简单到困难的两道题目带大家学会动…

根目录/ 空间不够,扩容,导致web页面无法加载问题

现象就是&#xff1a;搭建的web页面无反应&#xff0c;也没报错&#xff0c;怀疑是内存空间不够导致的。/ 扩容步骤如下&#xff1a; 虚拟机为关机状态添加虚拟磁盘 #查看磁盘&#xff0c;并创建新分区 fdisk -l fdisk /dev/sdb p       查看已分区数量&#xff08;我看…

在cmd下查看mysql表的结构信息

我提前已经在mysql数据库中创建了一个表&#xff1a; 在cmd下&#xff0c;登录mysql以后&#xff0c;使用命令describe 表名、或者explain 表名可以查看表结构信息。但在实践中&#xff0c;查看表结构&#xff0c;多用describe命令&#xff0c;而查看执行计划用explain。 例…

FreeRtos第一个task是怎么run起来的

第一个task是怎么起来的呢&#xff1f;分析完vTaskStartScheduler&#xff0c;就会有答案了。 那vTaskStartScheduler()干了啥呢&#xff1f; 一、创建prvIdleTask task 二、xTimerCreateTimerTask里创建prvTimerTask task 三、初始化一些全局变量 3.1 xNextTaskUnblockTime…

计算机组成学习-数据的表示和运算总结

1、进制与编码 1.1 进位计数法 常用的进位计数法有十进制、二进制、八进制、十六进制等。十六进制每个 数位可取0〜9、A、B、C、D、E、F中的任意一个&#xff0c;其中A、B、C、D、E、F分别表示 10〜15。 八进制数字通常以前缀 "0"&#xff08;零&#xff09;加上数…

前端文本省略号后面添加复制文字

前端文本省略号后面添加复制文字 1、效果图 2、代码展示 <div class"link-content-wrap" click"copyLinkText"><div class"link-content">{{ shareResult.url || }} </div><span class"show-ellipsis" click&…

「C++」哈希表的实现(unordered系底层)

&#x1f4bb;文章目录 &#x1f4c4;前言哈希表概念哈希函数 哈希冲突闭散列开散列 &#x1f4d3;总结 &#x1f4c4;前言 unordered系列的关联式容器之所以效率比较高,是因为其底层使用了哈希结构&#xff0c;使其在查找上的时间复杂度几乎减低到了 O ( 1 ) O(1) O(1)。 哈希…

微信扫码登录的两种方式:利用微信开放平台、利用微信公众平台(微信公众号)

微信扫码登录&#xff0c;有两种实现方式&#xff1a; 方式1、微信开放平台是微信为了接入更多第三方应用而开放的接口&#xff0c;依赖公司在【微信开放平台】用【公司营业执照】注册的账号&#xff0c;才能实现扫码登录 方式2、微信公众平台是扫码通过微信公众号授权登录的&a…

2023 如何下载最干净的 win10 win11 微软官方原版系统镜像(详细图文)

前言 不会吧不会吧&#xff0c;不会到现在还有人不会下载原版系统镜像吧 开始 win10官方下载工具下载地址&#xff1a;https://www.microsoft.com/zh-cn/software-download/windows10 win11官方下载工具下载地址&#xff1a;https://www.microsoft.com/zh-cn/software-downl…

Asp.net core WebApi 配置自定义swaggerUI和中文注释,Jwt Bearer配置

1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…

基于PLC的采摘机械手系统(论文+源码)

1.系统设计 本次设计围绕基于PLC的采摘机械手系统进行设计&#xff0c; PLC即可编程控制器其是一种常见的微处理器&#xff0c;本次拟采用西门子是S7-200 PLC&#xff0c;一方面对整个设计从器件选型到I/O分配&#xff0c;图纸绘制等进行设计&#xff0c;另一方面还通过组态王…

4/150:寻找两个正序数组的中位数⭐ 5/150最长回文子串

题目&#xff1a;4/150寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 题解1&#xff1a;暴力 暴力思路简介&#x…

uniapp运行到安卓基座app/img标签不显示

img是html中的标签&#xff0c;他也是一个单标签 image属于服务器控件&#xff0c;是个双标签 问题&#xff1a;uniapp运行到app安卓基座后图片无法显示 原因&#xff1a;自己使用了img标签&#xff0c;而且输入路径无提示&#xff0c;img标签导致图片不显示 解决&#xff…

J-LINK J-FLASH 下载STM32单片机程序使用教程

J-LINK J-FLASH 下载STM32单片机程序使用教程 Chapter1 J-LINK J-FLASH 下载STM32单片机程序使用教程1.安装提供的 JLINK驱动程序2. 点击打开 J-Flash V7.223.点击 create a new project.&#xff08;使用后可以在软件菜单File保存这个烧写工程&#xff0c;后续直接打开使用即可…

一篇带你串通数据结构

文章目录 导论数据结构的定义数据结构在计算机科学中的重要性为什么学习数据结构很重要 1、基本概念1.1、数据、数据元素和数据项的概念1.2、数据对象与数据结构的关系1.3、逻辑结构与物理结构 2、线性结构2.1、数组2.2、链表2.3、栈2.4、队列 3、非线性结构3.1、树3.2、图 4、…

九、FreeRTOS之FreeRTOS列表和列表项

本节需要掌握以下内容&#xff1a; 1&#xff0c;列表和列表项的简介&#xff08;熟悉&#xff09; 2&#xff0c;列表相关API函数介绍&#xff08;掌握&#xff09; 3&#xff0c;列表项的插入和删除实验&#xff08;掌握&#xff09; 4&#xff0c;课堂总结&#xff08;掌…