当前位置: 首页 > news >正文

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

前言:

前面我们已经把显示系统、输入系统、文字系统搭建好了,现在我们就要给它实现按钮操作了,也就是搭建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    0x000000struct 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)nmSTRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMPCFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/includeLDFLAGS := -lts -lpthread -lfreetypeexport CFLAGS LDFLAGSTOPDIR := $(shell pwd)
export TOPDIRTARGET := testobj-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.运行效果:

每隔两秒切换一下颜色

相关文章:

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

前言&#xff1a; 前面我们已经把显示系统、输入系统、文字系统搭建好了&#xff0c;现在我们就要给它实现按钮操作了&#xff0c;也就是搭建UI系统&#xff0c;下面让我们一起实现UI系统的搭建吧 目录 一、按钮数据结构抽象 ui.h 二、按键编程 1.button.c 2.disp_manager…...

面试就是这么简单,offer拿到手软(四)—— 常见java152道基础面试题

面试就是这么简单&#xff0c;offer拿到手软&#xff08;一&#xff09;—— 常见非技术问题回答思路 面试就是这么简单&#xff0c;offer拿到手软&#xff08;二&#xff09;—— 常见65道非技术面试问题 面试就是这么简单&#xff0c;offer拿到手软&#xff08;三&#xff…...

深入理解Redis分片策略:提升系统性能的关键一步

目录 引言 1. 一致性哈希算法 2. 范围分片 3. 哈希槽分片 实战经验分享 结论 引言 Redis作为一款高性能的键值存储系统&#xff0c;为了应对大规模数据和高并发的访问&#xff0c;引入了分片策略&#xff0c;使得数据能够分布存储在多个节点上&#xff0c;实现系统的横向…...

【数据结构(七)】查找算法

文章目录 查找算法介绍1. 线性查找算法2. 二分查找算法2.1. 思路分析2.2. 代码实现2.3. 功能拓展 3. 插值查找算法3.1. 前言3.2. 相关概念3.3. 实例应用 4. 斐波那契(黄金分割法)查找算法4.1. 斐波那契(黄金分割法)原理4.2. 实例应用 查找算法介绍 在 java 中&#xff0c;我们…...

Android画布Canvas绘制drawBitmap基于源Rect和目的Rect,Kotlin

Android画布Canvas绘制drawBitmap基于源Rect和目的Rect&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <androidx.appcompat.widget.LinearLayoutCompat xmlns:android"http://schemas.android.com/apk/res/android"xmlns…...

深度优先搜索LeetCode979. 在二叉树中分配硬币

给你一个有 n 个结点的二叉树的根结点 root &#xff0c;其中树中每个结点 node 都对应有 node.val 枚硬币。整棵树上一共有 n 枚硬币。 在一次移动中&#xff0c;我们可以选择两个相邻的结点&#xff0c;然后将一枚硬币从其中一个结点移动到另一个结点。移动可以是从父结点到…...

C++学习之路(十)C++ 用Qt5实现一个工具箱(增加一个时间戳转换功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《JSON数据格式化》功能&#xff0c;还是比较实用的。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加一个平时经常用到的功能吧&#xff0c;就是「 时间戳转换 」功能&#xff0c;而且实现点击按钮后文字进行变…...

Linux 5.15安全特性之ARM64 PAC

ARM64 PAC&#xff08;Pointer Authentication Code&#xff09;机制是ARM架构中引入的一种安全特性&#xff0c;旨在提供指针的完整性和安全性保护。它通过在指针中插入一段额外的代码进行签名&#xff0c;以验证指针的完整性&#xff0c;从而抵御缓冲区溢出和代码注入等攻击。…...

同旺科技 分布式数字温度传感器

内附链接 1、数字温度传感器 主要特性有&#xff1a; ● 支持PT100 / PT1000 两种铂电阻&#xff1b; ● 支持 2线 / 3线 / 4线 制接线方式&#xff1b; ● 支持5V&#xff5e;17V DC电源供电&#xff1b; ● 支持电源反接保护&#xff1b; ● 支持通讯波特率1200bps、2…...

状态空间的定义

状态空间是描述一个系统所有可能状态的集合。在系统理论、控制论、计算机科学、强化学习等领域&#xff0c;状态空间是一种常见的概念。 状态空间框架是一种用于描述和分析系统的方法&#xff0c;它包括系统的状态、状态之间的转移关系以及与状态相关的行为。下面详细解释状态…...

数据挖掘实战-基于word2vec的短文本情感分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…...

大数据面试总结

1、冒泡排序、选择排序 2、二分查找 3、 hashmap和hashtable的区别&#xff1f;hashmap的底层实现原理&#xff1f; a、hashtable和hashmap的区别&#xff1a; 1、hashtable是线程安全的&#xff0c;会在每一个方法中都添加方法synchronize&#xff08;同步机制&#xff09…...

利大于弊:物联网技术对电子商务渠道的影响

For Better or For Worse: Impacts of IoT Technology in e-Commerce Channel 物联网技术使用传感器和其他联网设备来手机和共享数据&#xff0c;并且被视为一种可以为供应链成员带来巨大的机会的突破性技术。本文的研究背景是&#xff1a;一个提供物联网基础设备的电子商务平…...

Python 元组详解(tuple)

文章目录 1 概述1.1 性质1.2 下标1.3 切片 2 常用方法2.1 访问&#xff1a;迭代、根据下标2.2 删除&#xff1a;del2.3 运算符&#xff1a;、*2.4 计算元组中元素个数&#xff1a;len()2.5 返回元组中元素最大值&#xff1a;max()2.6 返回元组中元素最小值&#xff1a;min()2.7…...

Redis部署-主从模式

目录 单点问题 主从模式 解析主从模式 配置redis主从模式 info replication命令查看复制相关的状态 断开复制关系 安全性 只读 传输延迟 拓扑结构 数据同步psync replicationid offset psync运行流程 全量复制流程 无硬盘模式 部分复制流程 积压缓冲区 实时复…...

全栈冲刺 之 一天速成MySQL

一、为什么使用数据库 数据储存在哪里&#xff1f; 硬盘、网盘、U盘、光盘、内存&#xff08;临时存储&#xff09; 数据持久化 使用文件来进行存储&#xff0c;数据库也是一种文件&#xff0c;像excel &#xff0c;xml 这些都可以进行数据的存储&#xff0c;但大量数据操作…...

服务器运行train.py报错解决

在服务器配置完虚拟环境以及安装完各种所需库后&#xff0c;发现报错Traceback (most recent call last): File "/root/yolov5-master/yolov5-master/train.py", line 48, in <module> import val as validate # for end-of-epoch mAP File "/root/yolov5…...

Flutter开发type ‘Future<int>‘ is not a subtype of type ‘int‘ in type cast错误

文章目录 问题描述错误源码 问题分析解决方法修改后的代码 问题描述 今天有个同事调试flutter程序时报错&#xff0c;问我怎么解决&#xff0c;程序运行时报如下错误&#xff1a; type ‘Future’ is not a subtype of type ‘int’ in type cast 错误源码 int order Databas…...

Nginx(十二) gzip gzip_static sendfile directio aio 组合使用测试(2)

测试10&#xff1a;开启gzip、sendfile、aio、directio1m&#xff0c;关闭gzip_static&#xff0c;请求/index.js {"time_iso8601":"2023-11-30T17:20:5508:00","request_uri":"/index.js","status":"200","…...

hls实现播放m3u8视频将视频流进行切片 HLS.js简介

github官网GitHub - video-dev/hls.js: HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.HLS.js is a JavaScript library that plays HLS in browsers with support for MSE. - GitHub - video-dev/hls.js: HLS.js is a JavaScript library …...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...