基于stm32使用ucgui+GUIBuilder开发ui实例
1 项目需求
1.1 基于Tft 触摸屏实现一个自锁按键
1.2 按键在按下后背景色需要进行变化,以凸显当前按键状态(选中or 未选中)
1.3 按键选中时对某一gpio输出低电平,非选中时输出高电平
2 移植 ucgui
UCGUI的文件数量很大,主要用到/Config 和 GUI两个文件夹下文件
相关文件介绍如下:
将Config和GUI下所有文件加入工程,MDK中新建工程需要划分好结构,这是UCGUI官方推荐的结构:
JPEG, MemDev , MultiLayer , Widget , Wm 这5 个文件夹的内容可以暂时不加入MDK工程。
因为这些文件起到的是扩展功能,在移植阶段可以先不添加,等到以后用到其中的功能时再选择添加。但是建议都添加进去,避免遇到各种无解问题。
ConverMono , ConverColor ,Core ,Font 这四个目录下的文件是不用修改的。要修改的文件在LCDDriver ,Config 这两个目录下。
LCDDriver 是LCD的驱动接口函数文件,需要将自己的LCD驱动函数提供给UCGUI调用。
需要提供3个LCD底层驱动函数:
- void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) LCD画点函数, 用指定颜色填充一个像素
- unsigned int LCD_L0_GetPixelIndex(int x, int y) LCD读取定点颜色函数,读取一个像素点的16位RGB颜色值
LCDDriver 下有三个文件, LCDDummy.c 、 LCDNull.c 和LCDWin.c。 这三个都是UCGUI LCD接口模板文件。功能一样,只是移植时修改的细节不一样。我们可以选用其中一个,稍作修改作为接口文件。以LCDDummy.c为例,需要把其中LCD_L0_SetPixelIndex、LCD_L0_GetPixelIndex接口函数基于自己开发板的进行实现。
详细移植参考
stm32 UCGUI 完美移植_基于stm32的ucgui移植手册-CSDN博客
考虑我使用的ucgui库不支持自锁按键的功能,分析源码后对源码进行了修改设计中通过GUI_GetKey()函数获取被按下的键值,通过按下键值在应用层进程自锁功能设计,调用按键背景颜色改变来实现按下后背景变化功能,想了解详细实现可下载源码进行分析
3 基于 GUIBuilder 设计ui交互
下载地址GUIBuilder下载地址 ucGUI模拟器资源-CSDN文库
3.1打开GUIBuilder,界面如下
3.2添加 window 窗体
3.3 添加3个 button按键,分别设置为button1、button2、button3
3.4 将以上ui设计导出为c文件,选择file 中save ,导出文件默认存储在GUIBuilder 当前软件目录下,名称为WindowDLG.c
3.5 WindowDLG.c文件内容如下
/*********************************************************************
* *
* SEGGER Microcontroller GmbH & Co. KG *
* Solutions for real time microcontroller applications *
* *
**********************************************************************
* *
* C-file generated by: *
* *
* GUI_Builder for emWin version 5.22 *
* Compiled Jul 4 2013, 15:16:01 *
* (c) 2013 Segger Microcontroller GmbH & Co. KG *
* *
**********************************************************************
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
*/
// USER START (Optionally insert additional includes)
// USER END
#include "DIALOG.h"
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
#define ID_WINDOW_0 (GUI_ID_USER + 0x00)
#define ID_BUTTON_0 (GUI_ID_USER + 0x01)
#define ID_BUTTON_1 (GUI_ID_USER + 0x02)
#define ID_BUTTON_2 (GUI_ID_USER + 0x03)
// USER START (Optionally insert additional defines)
// USER END
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
// USER START (Optionally insert additional static data)
// USER END
/*********************************************************************
*
* _aDialogCreate
*/
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
{ WINDOW_CreateIndirect, "Window", ID_WINDOW_0, -1, 1, 240, 320, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button1", ID_BUTTON_0, 25, 17, 181, 72, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button2", ID_BUTTON_1, 28, 125, 177, 74, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button3", ID_BUTTON_2, 26, 232, 179, 66, 0, 0x0, 0 },
// USER START (Optionally insert additional widgets)
// USER END
};
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
// USER START (Optionally insert additional static code)
// USER END
/*********************************************************************
*
* _cbDialog
*/
static void _cbDialog(WM_MESSAGE * pMsg) {
int NCode;
int Id;
// USER START (Optionally insert additional variables)
// USER END
switch (pMsg->MsgId) {
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc);
NCode = pMsg->Data.v;
switch(Id) {
case ID_BUTTON_0: // Notifications sent by 'Button1'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
case WM_NOTIFICATION_RELEASED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
// USER START (Optionally insert additional code for further notification handling)
// USER END
}
break;
case ID_BUTTON_1: // Notifications sent by 'Button2'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
case WM_NOTIFICATION_RELEASED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
// USER START (Optionally insert additional code for further notification handling)
// USER END
}
break;
case ID_BUTTON_2: // Notifications sent by 'Button3'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
case WM_NOTIFICATION_RELEASED:
// USER START (Optionally insert code for reacting on notification message)
// USER END
break;
// USER START (Optionally insert additional code for further notification handling)
// USER END
}
break;
// USER START (Optionally insert additional code for further Ids)
// USER END
}
break;
// USER START (Optionally insert additional message handling)
// USER END
default:
WM_DefaultProc(pMsg);
break;
}
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* CreateWindow
*/
WM_HWIN CreateWindow(void);
WM_HWIN CreateWindow(void) {
WM_HWIN hWin;
hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
return hWin;
}
// USER START (Optionally insert additional public code)
// USER END
/*************************** End of file ****************************/
考虑程序uggui库与GUIBuilder 导出的库有些兼容问题,先把源码中红色删除
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
{ WINDOW_CreateIndirect, "Window", ID_WINDOW_0, -1, 1, 240, 320, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button1", ID_BUTTON_0, 25, 17, 181, 72, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button2", ID_BUTTON_1, 28, 125, 177, 74, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "Button3", ID_BUTTON_2, 26, 232, 179, 66, 0, 0x0, 0 },
// USER START (Optionally insert additional widgets)
// USER END
};
3 移植GUIBuilder 导出的文件到工程项目中
在主程序中根据GUI_GetKey返回的当前被按下的键值进行自锁功能设计
比如,按下1次为选中,按下2两次为取消
对button1、button2、button3 进行逻辑互斥,只要一个按下其他都为取消
4 运行效果
4.1按下button1
4.2 按下button3
4.3 取消button3
5、 源码下载
基于stm32使用ucgui+GUIBuilder开发ui实例源码资源-CSDN文库
相关文章:

基于stm32使用ucgui+GUIBuilder开发ui实例
1 项目需求 1.1 基于Tft 触摸屏实现一个自锁按键 1.2 按键在按下后背景色需要进行变化,以凸显当前按键状态(选中or 未选中) 1.3 按键选中时对某一gpio输出低电平,非选中时输出高电平 2 移植 ucgui UCGUI的文件数量很大&#x…...

Spring扩展点系列-ApplicationContextAwareProcessor
文章目录 简介源码分析示例代码示例一:扩展点的执行顺序运行示例一 示例二:获取配置文件值配置文件application.properties内容定义工具类ConfigUtilcontroller测试调用运行示例二 示例三:实现ResourceLoaderAware读取文件ExtendResourceLoad…...
基于Keil软件实现实时时钟(江协科技HAL库)
实时时钟实验是基于江协科技STM32的HAL库工程模板创建的(可以在作品“基于江科大STM32创建的HAL库工程模板”中的结尾处获取工程模板的百度网盘链接) 复制“OLED显示”的工程文件——“4-1 OLED显示屏”,并命名为“12-2 实时时钟 ”。打开工程,把下面的程序复制到相应的文…...

dedecms靶场(四种webshell姿势)
进入靶场 姿势一:过文件管理器上传WebShell 步骤一:登录后台 /dede 步骤二:核心-》文件式管理-》文件上传-》上传一句话木马 点击 步骤三:进行蚁剑连接 姿势二:修改模板文件拿WebShell 步骤一:模板-》默认…...

PHP:强大的Web开发语言
PHP:强大的Web开发语言 一、PHP 简介及优势 PHP 的基本概念 PHP(PHP: Hypertext Preprocessor)即 “超文本预处理器”,是一种通用开源脚本语言,最初由 Rasmus Lerdorf 于 1994 年创建。它可以在服务器上执行…...

06_Python数据类型_元组
Python的基础数据类型 数值类型:整数、浮点数、复数、布尔字符串容器类型:列表、元祖、字典、集合 元组 元组(Tuple)是一种不可变的序列类型,与列表类似,但有一些关键的区别。本质:只读的列表…...
【Vue】- ref获取DOM元素和购物车案例分析
文章目录 知识回顾前言源码分析1. ref2. 购物车案例分析3. 购物车计算、全选 拓展知识数据持久化localStorage 总结 知识回顾 前言 元素上使用 ref属性关联响应式数据,获取DOM元素 步骤 ● 创建 ref > const hRef ref(null) ● 模板中建立关联 > <h1 re…...

【AI大模型】ChatGPT模型原理介绍(下)
目录 🍔 GPT-3介绍 1.1 GPT-3模型架构 1.2 GPT-3训练核心思想 1.3 GPT-3数据集 1.4 GPT-3模型的特点 1.5 GPT-3模型总结 🍔 ChatGPT介绍 2.1 ChatGPT原理 2.2 什么是强化学习 2.3 ChatGPT强化学习步骤 2.4 监督调优模型 2.5 训练奖励模型 2.…...
Python数据分析与可视化实战指南
在数据驱动的时代,Python因其简洁的语法、强大的库生态系统以及活跃的社区,成为了数据分析与可视化的首选语言。本文将通过一个详细的案例,带领大家学习如何使用Python进行数据分析,并通过可视化来直观呈现分析结果。 一、环境准…...

react18基础教程系列-- 框架基础理论知识mvc/jsx/createRoot
react的设计模式 React 是 mvc 体系,vue 是 mvvm 体系 mvc: model(数据)-view(视图)-controller(控制器) 我们需要按照专业的语法去构建 app 页面,react 使用的是 jsx 语法构建数据层,需要动态处理的的数据都要数据层支持控制层: 当我们需要…...
牛客周赛 Round 60 折返跑(组合数学)
题目链接:题目 大意: 在 1 1 1到 n n n之间往返跑m趟,推 m − 1 m-1 m−1次杆子,每次都向中间推,不能推零次,问有多少种推法(mod 1e97)。 思路: 一个高中学过的组合数…...
深入浅出Java匿名内部类:用法详解与实例演示
匿名内部类(Anonymous Inner Class)在Java中是一种非常有用的特性,它允许你在一个类的定义中直接创建并实例化一个内部类,而不需要为这个内部类指定一个名字。匿名内部类通常用于以下几种情况: 实现接口:当…...
数据库MySQL、Mariadb、PostgreSQL、MangoDB、Memcached和Redis详细介绍
以下是一些常见的后端开发数据库选型: 关系型数据库(RDBMS):关系型数据库是最常见的数据库类型,使用表格和关系模型来存储和管理数据。常见的关系型数据库包括MySQL、PostgreSQL和Oracle等。这些数据库适合处理结构化数…...

【ArcGIS Pro实操第七期】栅格数据合并、裁剪及统计:以全球不透水面积为例
【ArcGIS Pro实操第七期】批量裁剪:以全球不透水面积为例 准备:数据下载ArcGIS Pro批量裁剪数据集1 数据拼接2 数据裁剪3 数据统计:各栅格取值3.1 栅格计算器-精确提取-栅格数据特定值3.2 数据统计 4 不透水面积变化分析 参考 准备࿱…...
【Linux】Image、zImage与uImage的区别
1、Image 1.1 什么是 Image Image 是一种未压缩的 Linux 内核镜像文件,包含了内核的所有代码、数据和必要的元信息。它是 Linux 内核在编译过程中生成的一个原始的二进制文件,未经过任何压缩或额外的封装处理。由于未压缩,Image 文件相对较…...
算子加速(3):自定义cuda扩展
需要自定义某个层,或有时候用c++实现你的操作(c++扩展)可能会更好: 例如:需要实现一个新型的激活函数例如: bevfusion用cuda实现bevpool加速自定义扩展的步骤 (1) 首先用纯pytorch和python 实现我们所需的功能,看看效果再决定要不要进一步优化(2) 明确优化方向,用C++ (或CU…...

信息安全数学基础(14)欧拉函数
前言 在信息安全数学基础中,欧拉函数(Eulers Totient Function)是一个非常重要的概念,它与模运算、剩余类、简化剩余系以及密码学中的许多应用紧密相关。欧拉函数用符号 φ(n) 表示,其中 n 是一个正整数。 一、定义 欧…...

7-17 汉诺塔的非递归实现
输入样例: 3输出样例: a -> c a -> b c -> b a -> c b -> a b -> c a -> c 分析: 不会汉罗塔的uu们,先看看图解: 非递归代码: #include<iostream> #include<stack> using namespace std; s…...

word文档无损原样转pdf在windows平台使用python调用win32com使用pip安装pywin32
前提: windows环境下,并且安装了office套装,比如word,如果需要调用excel.也需要安装。在另外的文章会介绍。这种是直接调用word的。所以还原度会比较高。 需求: word文档转pdf,要求使用命令行形式,最终发布为api接口…...

海康威视相机在QTcreate上的使用教程
文章目录 前言:基础夯实:效果展示:图片展示:视频展示: 参考的资料:遇到问题:问题1:int64 does not问题2:LNK2019配置思路(这个很重要)配置关键图片:配置具体过…...
【Linux基础知识系列】第十一篇-Linux系统安全
Linux系统安全是指通过一系列技术和管理措施,保护Linux系统免受各种威胁和攻击,确保系统的完整性、可用性和机密性。随着网络攻击手段的多样化和复杂化,Linux系统安全成为了系统管理员和开发者必须面对的重要课题。本文将从用户认证、权限管理…...

android binder(四)binder驱动详解2
二、情景分析 1、ServiceManager 启动过程 2. 服务注册 服务注册过程(addService)核心功能:在服务所在进程创建binder_node,在servicemanager进程创建binder_ref。其中binder_ref的desc在同一个进程内是唯一的: 每个进程binder_proc所记录的…...
sizeof 与strlen的区别
sizeof 和 strlen 是C和C 中用于处理数据大小和字符串长度的两个不同的操作符/函数,它们的区别如下: 概念和用途 - sizeof 是一个操作符,用于计算数据类型或变量在内存中所占的字节数,它是在编译时确定的,与数据的…...

力扣HOT100之二分查找:4. 寻找两个正序数组的中位数
这道题如果没有时间复杂度的限制的话,相当好做,但是这道题要求时间复杂度为O(log(m n)),思路很难想,我看了一圈题解,发现华南溜达虎的视频讲得还不错,我是参考他的思路写出来的,这里把他的思路…...

【八股消消乐】构建微服务架构体系—服务注册与发现
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点ÿ…...
机器翻译模型笔记
机器翻译学习笔记(简体中文) 1. 任务概述 目标:将英文句子翻译成简体中文。 示例: 输入:Tom is a student. 输出:汤姆是一个学生。 框架:Seq2Seq(序列到序列)模型。…...

【学习笔记】Python金融基础
Python金融入门 1. 加载数据与可视化1.1. 加载数据1.2. 折线图1.3. 重采样1.4. K线图 / 蜡烛图1.5. 挑战1 2. 计算2.1. 收益 / 回报2.2. 绘制收益图2.3. 累积收益2.4. 波动率2.5. 挑战2 3. 滚动窗口3.1. 创建移动平均线3.2. 绘制移动平均线3.3 Challenge 4. 技术分析4.1. OBV4.…...
C++动态规划-线性DP
这是一套C线性DP题目的答案。如果需要题目,请私信我,我将会更新题干 P1:单子序列最大和 #include <bits/stdc.h> using namespace std; int n,A,B,C; int a[200005]; int s[200005]; int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)…...

Linux中su与sudo命令的区别:权限管理的关键差异解析
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
【Kotlin】注解反射扩展
文章目录 注解用法反射类引用 扩展扩展函数的作用域成员方法优先级总高于扩展函数 被滥用的扩展函数扩展属性静态扩展 标准库中的扩展函数 使用 T.also 函数交换两个变量sNullOrEmpty | isNullOrBlankwith函数repeat函数 调度方式对扩展函数的影响静态与动态调度扩展函数始终静…...