-
TinyUI
2020-04-30 16:27:01TinyUI是本人在疫情期间开发的一套可移植的UI库,如果感兴趣的人比较多将开源出来。 ------------------------------------------------------------------------------------------------------------------------...TinyUI是本人在疫情期间开发的一套可移植的嵌入式UI库,如果感兴趣的人比较多将开源出来。
---------------------------------------------------------------------------------------------------------------------------------
windows模拟器演示程序。
下载地址:https://pan.baidu.com/s/1b7f0zfAe6KnKGL3vhicc6g
提取码: yp6q---------------------------------------------------------------------------------------------------------------------------------
TinyUI相关博客:
3. TinyUI-TUIListView多列文本显示最简单的使用
5. TinyUI-按键对接
TinyUI简介:
TinyUI是一套适用于嵌入式平台开发的UI库,具有比较完整的事件驱动系统,该UI库使用方便简单。
目前基于低端嵌入式UI大多使用C语言进行开发或设计界面时需要计算UI组件/控件坐标,无法提高产品开发效率,或大多数嵌入式开发人员自行涉及UI,大多设计都在中断中显示UI或处理业务逻辑。另外一个更重要的问题即是无法自适应不同尺寸的屏幕,每开发新的产品或更换屏幕时都需要大量的修改或重写。
本UI库使用C++(C++ 11或以上版本)进行开发,其大多数UI组件/控件均参考主流平台进行设计,如ListView、GridView、LinearLayout、Spinner、ScrollView、TabView、Dialog等UI组件基本设计与Android一致,并且这些UI组件/控件的使用方法均与Android APP开发一致;其中GridLayout的使用方法与WPF/UWP基本一致。
TinyUI主要特点:
1. 提供LinearLayout和GridLayout等2种UI布局,可自适应不同尺寸屏幕,并且可以布局嵌套;
2. UI组件/控件使用简单,与主流平台设计相似;
3. 对于处理器是否集成LCD控制器均支持,并且如果内存够大还可以支持双缓存,可支持任意大小尺寸屏幕;
4. 对无触摸(但需要有按键),几乎所有可获得焦点的UI组件/控件均可绑定按键,当物理按键按下时UI组件/控件自动响应事件,而无需开发人员进行处理;
5. 所有的UI组件/控件可用功能比较丰富,如: TextView提供多种对齐、跑马方式,以及省略号结尾等;
6. 移植简单,底层驱动只需实现TinyUI定义的4个接口即可,如: LCD、按键、定时器、触摸;
7. TinyUI使用自定义字库(支持矢量字体与非矢量字体);
7.1 矢量字体
矢量字体显示使得文字细节非常丰富(把本模拟器截图粘贴到windows自带画图中,放大数倍即可看到字体细节),字体放大后的效果如下;
7.2 非矢量字体
8. TinyUI可移植目标平台丰富;
9. TinyUI使用UTF8编码;
10. 与硬件外设无关的应用可使用Visual studio并基于模拟器进行开发;
目前模拟器未使用鼠标钩子,使用钩子需要转换坐标:),有时鼠标抬起事件会丢失。TinyUI由本人/个人开发&测试,开发时间不足2个月,因此部分小UI组件/控件还未完成,同时会存在一定的BUG。
------------- TinyUI非常年轻,它的的发展需要大家的支持,您的支持将是我最大的动力。
如下贴出部分演示代码:
AboutWindow.h
class AboutWindow : public TUIWindow, public TUIButtonListener { public: AboutWindow(TUIWindow* parent = nullptr); virtual ~AboutWindow(); void onShow(); void onClose(); void onClick(TUIButton* view); private: TUIGridLayout rootLayout; // 顶层内容视图使用GridLayout TUIButton backButton; // 返回按钮 };
AboutWindow.cpp
AboutWindow::AboutWindow(TUIWindow* parent) : TUIWindow(parent) { setContentView(&this->rootLayout); // 设置GridLayout为当前窗口的内容视图 this->rootLayout.setRowNumber(3); // 3行 this->rootLayout.setColumnNumber(2); // 3列 this->rootLayout.setRowHeight(0, 30); // 第1行高30 this->rootLayout.setRowHeight(1, 30); // 第2行高30 this->rootLayout.setRowHeight(2, TUILAYOUT_DIM::TUI_MATCH_REMAIN); // 第3行高占满剩余空间 this->rootLayout.setColumnWidth(0, 50); // 第1列宽50 this->rootLayout.setColumnWidth(1, TUILAYOUT_DIM::TUI_MATCH_REMAIN); // 第2列占满剩余空间 this->backButton.setText(L"返回"); this->backButton.setMargin(2, 0, 2, 0); // 设置按钮外边距(顺序: 左->上->右->下) this->backButton.registerListener(this); // 当前窗口监听backButton点击事件 this->backButton.bindKeycode(TUIVKCode::TUIVK_BACK); // backButton绑定回退键 this->rootLayout.addView(&this->backButton, 0, 0); // backButton放到第0行,第0列 }
显示AboutWindow:
aboutWindow.show();
移植
TinyUI本身并不需要使用者做大量的工作,除非你需要更高级的功能(需要提供一个软中断给TinyUI)。
移植的难易程度取决于你的驱动结构好坏。
注: 我的驱动是C写的
1. 定时器接口移植
UITimer::UITimer(int32_t id) { if (0 == id) { normal_timer = (timer_t *)device_driver_autowired(DDTYPE_TIMER, DDID_TIMER02); normal_timer->ops->open(TIMER_MILLISECOND, TIMER_CONTINUOUS); } } UITimer::~UITimer() { } void UITimer::start(uint32_t millisecond) { if (nullptr == normal_timer) { return; } normal_timer->ops->start(millisecond); } void UITimer::stop() { if (nullptr == normal_timer) { return; } normal_timer->ops->close(); } void UITimer::registerCallback(timeoutCallback callback) { if (nullptr == normal_timer) { return; } normal_timer->ops->register_timeout_callback(callback); }
2. LCD接口移植
UIDisplay::UIDisplay() { ili9341 = (lcd_controller_t *)device_driver_autowired(DDTYPE_LCD_CONTROLLER, DDID_LCD_CONTROLLER_ILI9341); ili9341->ops->open(); } UIDisplay::~UIDisplay() { } bool UIDisplay::readPoint(int32_t x, int32_t y, color_t* color) { uint16_t c = 0; ili9341->ops->read_point(x, y, &c); *color = c; return true; } void UIDisplay::drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->draw_point(x, y, color); } void UIDisplay::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->draw_line(x1, y1, x2, y2, color); } void UIDisplay::drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer) { ili9341->ops->draw_buffer(x, y, bufferWidth, bufferHeight, buffer); } void UIDisplay::clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->clear(x, y, width, height, color); } uint8_t UIDisplay::getBPP() { return ili9341->ops->get_bpp(); } uint32_t UIDisplay::getScreenWidth() { return ili9341->ops->get_width(); } uint32_t UIDisplay::getScreenHeight() { return ili9341->ops->get_height(); } uint8_t* UIDisplay::getFB() { //return g_FrameBuffer; // 不支持 return nullptr; } void UIDisplay::submit(uint8_t* buffer) { //ili9341->ops->draw_buffer(0, 0, 320, 240, g_FrameBuffer); // 不支持 }
3. TinyUI初始化及驱动
void initTinyUI() { TUIInit(); // Tiny初始化 UIDisplay *display = new UIDisplay(); TUIRegisterFBInterface(display); // 注册显示接口 UITimer *timer0 = new UITimer(0); // 实例化一个定时器给TinyUI使用 TUIRegisterTimerInterface(0, timer0); string filePath = "1:font.tui"; // 字库路径 TUIRegisterFontInterface(TUIFontRenderer::instance(), filePath.c_str()); // 注册字体渲染器,TinyUI运行自定义 MyLauncher* myLauncher = new MyLauncher(); // 定义自己的主界面 TUIStartup(myLauncher); // 把自己的主界面注册到TinyUI中 }
-
TinyUI-windows模拟器演示程序
2020-05-10 18:21:36TinyUI是一套适用于嵌入式平台开发的UI库,具有比较完整的事件驱动系统,该UI库使用方便简单。 本UI库使用C++(C++ 11或以上版本)进行开发,其大多数UI组件/控件均参考主流平台进行设计,如ListView、GridView、... -
TinyUI:Playfield,用于测试创意-源码
2021-02-14 20:38:05TinyUI TinyUI是一个小型库,用于创建.NET控制台应用程序的按钮和输入字段,并使用键盘在这些字段之间导航,目前不支持鼠标导航。 该库是作为学生项目创建的。 教程 创建一个空的.NET控制台项目,将此存储库克隆到... -
TinyUI-按键对接
2020-05-06 20:38:15对于无触摸的嵌入式设备来说,按键就是整个人机交互的入口点,TinyUI定义了按键接口类TUIKeyInterface,当需要把底层驱动和TinyUI对接时,需要实现一个自定义按键类,继承自TUIKeyInterface接口即可,最后把自定义...对于无触摸的嵌入式设备来说,按键就是整个人机交互的入口点,TinyUI定义了按键接口类TUIKeyInterface,当需要把底层驱动和TinyUI对接时,需要实现一个自定义按键类,继承自TUIKeyInterface接口即可,最后把自定义按键类实例化,并调用TinyUI的按键注册接口TUIRegisterKeyInterface即可。
TUIKeyInterface只有一个方法需要开发人员实现,即registerCallback(),当驱动把自定义按键类实例注册到TinyUI时,TinyUI注册回调方法给驱动,当按钮产生中断时调用该接口注册的回调方法即可,TUIKeyInterface定义如下:
#ifndef __TUI_KEY_INTERFACE_H__ #define __TUI_KEY_INTERFACE_H__ #include <TUIVKCode.h> #include <TUIAction.h> typedef void (*KeyCallback)(TUIACTION_KEY action, TUIVKCode keyCode); class TUIKeyInterface { public: virtual void registerCallback(KeyCallback callback) = 0; }; #endif // !__TUI_KEY_INTERFACE_H__
该回调方法有2个参数分别是TUIACTION_KEY和TUIVKCode,TUIACTION_KEY代表按键是按下还是弹起,其定义如下:
enum class TUIACTION_KEY : uint8_t { TUI_DOWN, // 按键按下(物理按键) TUI_UP, // 按键弹起(物理按键) };
TUIVKCode是TinyUI定义的虚拟按键码,其定义了大部分常用快捷键如F1~F12,上、下、左、右等等,移植时根据实际情况发出对应的键码和动作(按下还是弹起)。
移植
1. 自定义按键类,并继承自TUIKeyInterface
UIKey.h
#ifndef __UI_KEY_H__ #define __UI_KEY_H__ #include "device_driver_ioc.h" #include <TUIKeyInterface.h> class UIKey : public TUIKeyInterface { public: UIKey(); virtual ~UIKey(); public: void registerCallback(KeyCallback callback); private: input_t *input = nullptr; // 驱动中的按键实例/对象 }; #endif
UIKey.cpp
#include <UIKey.h> #include <TUIVKCode.h> #include <TUIAction.h> KeyCallback gCallBack = nullptr; // 定义TinyUI回调接口 /* 由于驱动中的按键定义的回调方法和TinyUI不一致,把该方法注册到驱动作为回调 当有按键产生时,在该方法中调用gCallBack,把按键传递到TinyUI中 */ void UIKey_input_input_callback(enum VK_ACT act, enum VK_CODE vcode) { if (nullptr == gCallBack) // 判断TinyUI是否注册了回调 { return; } TUIACTION_KEY action; uint32_t vk = (uint32_t)vcode; // 驱动和TinyUI按键值都是枚举,转换一次 /* 按键中断定义的按下和抬起与TinyUI不一致,此处转换一次 */ if (VACT_DOWN == act) { action = TUIACTION_KEY::TUI_DOWN; // 按下 } else if (VACT_UP == act) { action = TUIACTION_KEY::TUI_UP; // 弹起 } gCallBack(action, (TUIVKCode)vk); // 调用TinyUI的回调函数 } UIKey::UIKey() { input = (input_t *)device_driver_autowired(DDTYPE_INPUT, DDID_INPUT_BUTTON); // 使用依赖注入技术获取驱动的按键实例 if (nullptr != input) { input->ops->register_input_callback(UIKey_input_input_callback); // 把UIKey_input_input_callback注册到按键中断回调中 input->ops->open(); // 打开按键驱动 } } UIKey::~UIKey() { input->ops->close(); // 关闭按键驱动 } void UIKey::registerCallback(KeyCallback callback) { gCallBack = callback; // gCallBack指向TinyUI的回调函数 }
2. 实例化UIKey并注册到TinyUI中
UIKey* key = new UIKey(); TUIRegisterKeyInterface(key);
-
TinyUI-LCD驱动对接
2020-05-04 19:08:58TinyUI对于MCU是否集成LCD控制器都支持,但需要实现TinyUI定义的TUIFBInterface纯虚类接口,FB为frame buffer的缩写。该接口部分方法是否需要实现依赖于当前需要移植的MCU是否集成LCD控制器,如果集成了LCD控制器,...TinyUI对于MCU是否集成LCD控制器都支持,但需要实现TinyUI定义的TUIFBInterface纯虚类接口,FB为frame buffer的缩写。该接口部分方法是否需要实现依赖于当前需要移植的MCU是否集成LCD控制器,如果集成了LCD控制器,则只需实现极少部分的方法,但是如果MCU未集成LCD控制器,则可能需要实现大部分的方法。
TinyUI定义的显示接口
TUIFBInterface.h
#ifndef __TUI_FB_INTERFACE__ #define __TUI_FB_INTERFACE__ #include <TUITypes.h> class TUIFBInterface { public: /********************************************************************************************************************* @Function: readPoint @Description: 获取LCD某个像素的颜色值 1. 未集成LCD控制器的MCU重写该方法,若不支持,则返回false。 2. 集成LCD控制器的MCU不需要重写该方法 @Param: x: 待读取像素值的水平坐标 y: 待读取像素值的垂直坐标 color: 输出参数,返回该像素点的颜色值 @Return: true: 支持读取像素;false: 不支持读取像素 ***********************************************************************************************************************/ virtual bool readPoint(int32_t x, int32_t y, color_t* color) { return false; } /********************************************************************************************************************* @Function: drawPoint @Description: 在指定位置(x, y)绘制一个点 1. 未集成LCD控制器的MCU必须立即绘制。 2. 集成LCD控制器的MCU实现空方法即可。 @Param: x: 绘制点的水平坐标 y: 绘制点的垂直坐标 visibleX1: 水平绘制坐标左边界,当x小于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现 visibleY1: 垂直绘制坐标上边界,当y小于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现 visibleX2: 水平绘制坐标右边界,当x大于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现 visibleY2: 垂直绘制坐标下边界,当y大于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现 color: 绘制点的颜色 @Return: none ***********************************************************************************************************************/ virtual void drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0; /********************************************************************************************************************* @Function: drawLine @Description: 从指定位置(x1, y1)到(x2, y2)绘制一条直线 1. 未集成LCD控制器的MCU必须立即绘制。 2. 集成LCD控制器的MCU实现空方法即可。 @Param: x1: 绘制直线的水平起始坐标 y1: 绘制直线的垂直起始坐标 x2: 绘制直线的水平结束坐标 y2: 绘制直线的垂直结束坐标 visibleX1: 水平绘制坐标左边界,当x1或x2小于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY1: 垂直绘制坐标上边界,当y1或y2小于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现 visibleX2: 水平绘制坐标右边界,当x1或x2大于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY2: 垂直绘制坐标下边界,当y1或y2大于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现 color: 绘制点的颜色 @Return: none ***********************************************************************************************************************/ virtual void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0; /********************************************************************************************************************* @Function: drawBuffer @Description: 从指定左上角位置(x,y)开始绘制一段内存数据 该内存数据按照从左到右,从上到下进行绘制,该内存数据可以为图片/字体或一个矩形区域数据 1. 未集成LCD控制器的MCU必须立即绘制。 2. 集成LCD控制器的MCU实现空方法即可。 @Param: x: 绘制点的左上角水平坐标 y: 绘制点的左上角垂直坐标 bufferWidth: 内存数据的宽度 bufferHeight: 内存数据的高度 visibleX1: 水平绘制坐标左边界,当x小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY1: 垂直绘制坐标上边界,当y小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现 visibleX2: 水平绘制坐标右边界,当(x + bufferWidth - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY2: 垂直绘制坐标下边界,当(y + bufferHeight - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现 buffer: 内存数据(颜色数据),数据为大端模式 @Return: none ***********************************************************************************************************************/ virtual void drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer) = 0; /********************************************************************************************************************* @Function: clear @Description: 从指定左上角位置(x,y)开始,使用指定颜色对一块矩形区域清除 1. 未集成LCD控制器的MCU必须立即绘制。 2. 集成LCD控制器的MCU实现空方法即可。 @Param: x: 绘制点的左上角水平坐标 y: 绘制点的左上角垂直坐标 width: 矩形区域的宽度 height: 矩形区域的高度 visibleX1: 水平绘制坐标左边界,当x小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY1: 垂直绘制坐标上边界,当y小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现 visibleX2: 水平绘制坐标右边界,当(x + width - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现 visibleY2: 垂直绘制坐标下边界,当(y + height - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现 color: 绘制点的颜色 @Return: none ***********************************************************************************************************************/ virtual void clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0; /********************************************************************************************************************* @Function: getBPP @Description: 获取LCD像素深度,如16BPP(RGB565), 18BPP(RGB888) @Param: none @Return: 像素深度,如16, 18, 24等 ***********************************************************************************************************************/ virtual uint8_t getBPP() = 0; /********************************************************************************************************************* @Function: getScreenWidth @Description: 获取LCD宽度(像素) @Param: none @Return: 宽度值,如: 320, 800, 1920 ***********************************************************************************************************************/ virtual uint32_t getScreenWidth() = 0; /********************************************************************************************************************* @Function: getScreenHeight @Description: 获取LCD高度(像素) @Param: none @Return: 宽度值,如: 240, 480, 1080 ***********************************************************************************************************************/ virtual uint32_t getScreenHeight() = 0; /********************************************************************************************************************* @Function: getFB @Description: 获取显存 1. 未集成LCD控制器的MCU返回nullptr 2. 成LCD控制器的MCU返回某一块内存首地址,内存大小 = LCD宽度 * LCD高度 * (像素深度 / 8) @Param: none @Return: 内存地址 ***********************************************************************************************************************/ virtual uint8_t* getFB() = 0; /********************************************************************************************************************* @Function: submit @Description: GDI提交数据,代表GDI需要刷新一屏数据至LCD进行显示 1. 未集成LCD控制器的MCU可以执行一些收尾工作或实现空方法 2. 集成LCD控制器的MCU,此时必须完成窗口/层(双缓存切换),并准备好另一块缓存供GDI使用 @Param: buffer: GDI当前持有的显存 @Return: none ***********************************************************************************************************************/ virtual void submit(uint8_t* buffer) = 0; }; #endif // !__TUI_FB_INTERFACE__
未集成LCD控制器的MCU
1. 必须实现的接口如下:
1. drawPoint()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制点的操作。
2. drawLine()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制线的操作。
3. drawBuffer()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制小缓存的操作。该缓存可能是一个字符的位图,或其他小缓存,该缓存具有长和宽的特性。
4. clear()
当TinyUI调用该方法时,LCD驱动必须使用指定的颜色清除参数指定的矩形区域。
5. getBPP()
当TinyUI调用该方法时,LCD驱动返回当前LCD的像素深度,如16位、24位、32位等。
6. getScreenWidth()
当TinyUI调用该方法时,LCD驱动返回当前LCD的水平宽(像素)
7. getScreenHeight()
当TinyUI调用该方法时,LCD驱动返回当前LCD的垂直高(像素)
2. 可选实现方法
1. readPoint()
读取某一个像素点当前的颜色值,主要用于实现透明效果。
集成LCD控制器的MCU
1. 必须实现的接口
1. getBPP()
当TinyUI调用该方法时,LCD驱动返回当前LCD的像素深度,如16位、24位、32位等。
2. getScreenWidth()
当TinyUI调用该方法时,LCD驱动返回当前LCD的水平宽(像素)
3. getScreenHeight()
当TinyUI调用该方法时,LCD驱动返回当前LCD的垂直高(像素)
4. getFB()
一般情况下,集成了LCD控制器的MCU,外匹配的可用内存相对比较大,因为LCD控制器一般都会提供多个窗口或显示层,窗口或显示层即是我们通常所说的缓存概念,提高LCD刷新率。
该方法主要用于获取显存,LCD驱动返回显存首地址即可。
5. submit()
该方法用于提交并显示当前显存内容,LCD驱动底层需执行响应显存的切换动作,并返回原有显存或另一个显存(多窗口或多显示层一般都设计双缓存)
移植示例
本示例主要使用STM32F103为例进行演示,STM32F103未集成LCD控制器,而是使用FSMC接口控制ILI9341控制器对LCD进行控制,LCD分辨率为320x240。
本示例中使用的LCD驱动使用了目前后台开发比较流行的依赖注入技术,移植过程中可以看到调用device_driver_autowired()获取某一个驱动,本示例的LCD驱动也是使用C语言编写的。
移植步骤
1. 创建UIDisplay.h
1) 并包含TUIFBInterface.h
2) 定义UIDisplay类,并继承自TUIFBInterface
ifndef __UI_DISPLAY_H__ #define __UI_DISPLAY_H__ #include "device_driver_ioc.h" #include <TUIFBIntface.h> class UIDisplay : public TUIFBInterface { public: UIDisplay(); virtual ~UIDisplay(); /* 声明TUIFBInterface所有方法 */ public: bool readPoint(int32_t x, int32_t y, color_t* color); void drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color); void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color); void drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer); void clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color); uint8_t getBPP(); uint32_t getScreenWidth(); uint32_t getScreenHeight(); uint8_t* getFB(); void submit(uint8_t* buffer); private: lcd_controller_t *ili9341 = nullptr; // ILI9341驱动对象 };
2. 创建UIDisplay.cpp,并实现UIDisplay.h中的方法
#include <UIDisplay.h> UIDisplay::UIDisplay() { ili9341 = (lcd_controller_t *)device_driver_autowired(DDTYPE_LCD_CONTROLLER, DDID_LCD_CONTROLLER_ILI9341); ili9341->ops->open(); } UIDisplay::~UIDisplay() { ili9341->ops->close(); } bool UIDisplay::readPoint(int32_t x, int32_t y, color_t* color) { uint16_t c = 0; ili9341->ops->read_point(x, y, &c); *color = c; return true; } void UIDisplay::drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->draw_point(x, y, color); } void UIDisplay::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->draw_line(x1, y1, x2, y2, color); } void UIDisplay::drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer) { ili9341->ops->draw_buffer(x, y, bufferWidth, bufferHeight, buffer); } void UIDisplay::clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) { ili9341->ops->clear(x, y, width, height, color); } uint8_t UIDisplay::getBPP() { return ili9341->ops->get_bpp(); } uint32_t UIDisplay::getScreenWidth() { return ili9341->ops->get_width(); } uint32_t UIDisplay::getScreenHeight() { return ili9341->ops->get_height(); } uint8_t* UIDisplay::getFB() { return nullptr; // 无LCD控制器,返回nullptr即可 } void UIDisplay::submit(uint8_t* buffer) { // 无LCD控制器,空方法 }
向TinyUI注册LCD接口
UIDisplay *display = new UIDisplay(); LUIRegisterFBInterface(display);
模拟程序演示Button&ListView测试在STM32F103显示效果
第一行置顶,滚动到第10行,再回滚到第6行的效果
-
判断按键值_TinyUI(嵌入式UI库)-按键移植
2021-01-12 09:49:23TinyUI是一套用于嵌入式开发的UI库。TinyUI定义了与windows类似的虚拟按键码,一般嵌入式设备可能会有物理按键,物理按键可以与虚拟键码绑定/关联,期望当按下物理按键后(需把虚拟键码和界面元素进行绑定),界面可以...TinyUI是一套用于嵌入式开发的UI库。
TinyUI定义了与windows类似的虚拟按键码,一般嵌入式设备可能会有物理按键,物理按键可以与虚拟键码绑定/关联,期望当按下物理按键后(需把虚拟键码和界面元素进行绑定),界面可以得到相应并执行相应的操作。
对于无触摸的嵌入式设备来说,按键就是整个人机交互的入口点,TinyUI定义了按键接口类TUIKeyInterface,当需要把底层驱动和TinyUI对接时,需要实现一个自定义按键类,继承自TUIKeyInterface接口即可,最后把自定义按键类实例化,并调用TinyUI的按键注册接口TUIRegisterKeyInterface即可。
TUIKeyInterface只有一个方法需要开发人员实现,即registerCallback(),当驱动把自定义按键类实例注册到TinyUI时,TinyUI注册回调方法给驱动,当按钮产生中断时调用该接口注册的回调方法即可,TUIKeyInterface定义如下:
#ifndef __TUI_KEY_INTERFACE_H__#define __TUI_KEY_INTERFACE_H__#include #include typedef void (*KeyCallback)(TUIACTION_KEY action, TUIVKCode keyCode);class TUIKeyInterface{public: virtual void registerCallback(KeyCallback callback) = 0; // TinyUI向驱动层注册回调};#endif // !__TUI_KEY_INTERFACE_H__
该回调方法有2个参数分别是TUIACTION_KEY和TUIVKCode,TUIACTION_KEY代表按键是按下还是弹起,其定义如下:
enum class TUIACTION_KEY : uint8_t{ TUI_DOWN, // 按键按下(物理按键) TUI_UP, // 按键弹起(物理按键)};
TUIVKCode是TinyUI定义的虚拟按键码,其定义了大部分常用快捷键如F1~F12,上、下、左、右等等,移植时根据实际情况发出对应的键码和动作(按下还是弹起)。
移植
1. 自定义按键类,并继承自TUIKeyInterface
UIKey.h
#ifndef __UI_KEY_H__#define __UI_KEY_H__#include "device_driver_ioc.h"#include class UIKey : public TUIKeyInterface{public: UIKey(); virtual ~UIKey();public: void registerCallback(KeyCallback callback); // 调用TUIRegisterKeyInterface(key)注册物理按键后,TinyUI将注册回调函数到驱动层,以响应按键事件private: input_t *input = nullptr; // 驱动中的按键实例/对象};#endif
UIKey.cpp
#include #include #include KeyCallback gCallBack = nullptr; // 定义TinyUI回调接口/* 由于驱动中的按键键码定义和TinyUI所定义键码不一致,把该方法注册到驱动作为回调 当有按键产生时,在该方法中调用gCallBack,把按键传递到TinyUI中*/void UIKey_input_input_callback(enum VK_ACT act, enum VK_CODE vcode){ if (nullptr == gCallBack) // 判断TinyUI是否注册了回调 { return; } TUIACTION_KEY action; uint32_t vk = (uint32_t)vcode; // 驱动和TinyUI按键值都是枚举,转换一次 /* 按键中断定义的按下和抬起与TinyUI不一致,此处转换一次 */ if (VACT_DOWN == act) { action = TUIACTION_KEY::TUI_DOWN; // 按下 } else if (VACT_UP == act) { action = TUIACTION_KEY::TUI_UP; // 弹起 } gCallBack(action, (TUIVKCode)vk); // 调用TinyUI的回调函数}UIKey::UIKey(){ input = (input_t *)device_driver_autowired(DDTYPE_INPUT, DDID_INPUT_BUTTON); // 使用依赖注入技术获取驱动的按键实例 if (nullptr != input) { input->ops->register_input_callback(UIKey_input_input_callback); // 把UIKey_input_input_callback注册到按键中断回调中 input->ops->open(); // 打开按键驱动 }}UIKey::~UIKey(){ input->ops->close(); // 关闭按键驱动}void UIKey::registerCallback(KeyCallback callback){ gCallBack = callback; // gCallBack指向TinyUI的回调函数}
2. 实例化UIKey并注册到TinyUI中
UIKey* key = new UIKey();TUIRegisterKeyInterface(key); // 把UIKey注册到TinyUI中,当物理按键按下后,TinyUI将可以得到按键事件
至此,TinyUI可以响应物理按键了(如TUIButton,TUIListView等界面元素可以绑定键码)
注:本示例中的芯片为ST的STM32F103芯片,驱动使用了类似linux的总线,所有驱动都挂载在该总线上,通过设备名或id获取对应的驱动对象(如uart_t/iic_t/spi_t/lcd_control_t)。
-
TinyUI-TUIListView最简单的使用
2021-01-03 14:27:17在TinyUI简介的博客中提到其特点中包含一条,即多数大控件的使用方法和android一直,除了语言差异之外,本篇我们就介绍列表控件TUIListView最简单的使用方法。 列表组件/控件作为目前Android/iOS的APP中最常用的... -
TinyUI C++轻量级界面库
2014-12-24 15:36:10TinyUI C++轻量级界面库 有兴趣的下载下俩看看 -
TinyUI组件开发示例
2016-05-09 14:01:05TinyUI实际上并不是一个具体的UI展现组件,它只是一个UI构建体系。它可以适应于各种Html+CSS+JS的体系架构中。 TinyUI主要解决下面的问题: UI中JS的引入与顺序,JS合并的问题 UI中css的引入与顺序,CSS合并的问题 ... -
TinyUI-TUIWindow-最简单的自定义
2020-05-03 20:31:14TinyUI与传统Windows开发类似,使用窗口(TUIWindow)作为其他UI组件的载体,其设计模式与传统windows、Android等平台开发类似属于MVC设计模式。 但TinyUI作为轻量级的UI库,开发者可以把它与其他第三方UI库一样使用... -
分割view窗口不响应onmousewheel_TinyUI(嵌入式UI库)-窗口自定义
2020-12-13 02:25:08TinyUI与传统Windows开发类似,使用窗口(TUIWindow)作为其他UI组件的载体,其设计模式与传统windows、Android等平台开发类似属于MVC设计模式。但TinyUI作为轻量级的UI库,开发者可以把它与其他第三方UI库一样使用,... -
tiny UI improvements
2020-12-03 01:19:24<div><p>Some small UI fixes that need to be done: 1. the settings button and the arrow to open a folder have that ugly dotted border of active 2. items in folders look different than items in root ... -
TinyUI-TUIListView多列文本显示最简单的使用
2020-05-04 16:10:52在上一篇TinyUI-TUIListView最简单的使用中介绍了TUIListView单列文本最基本的事情情况,显示使用TinyUI内置的TUISimpleAdapter可以很轻松的完成单列文本列表。 实际开发过程中可能需要有多列显示情况,如果只需... -
java设置背景图片不覆盖组件_TinyUI(嵌入式UI库)-TUIButton组件
2020-12-03 02:12:29TinyUI是一套适用于嵌入式的UI库,目前已移植到STM32F103上。TinyUI支持界面布局,因此,UI组件使用都非常简单,与TUITextView一样,TUIButton使用也非常简单,TUIButton提供了如下API:/**************************... -
c中tabpage控件上显示的文本_TinyUI(嵌入式UI库)-列表单列显示
2020-11-27 15:26:24在TinyUI简介的博客中提到其特点中包含一条,即多数大控件的使用方法和android一直,除了语言差异之外,本篇我们就介绍列表控件TUIListView最简单的使用方法。列表组件/控件作为目前Android/iOS的APP中最常用的控件... -
TinyUI入门实践之快速构建个人网站
2014-11-26 12:29:24http://my.oschina.net/tinyframework/blog?catalog=377413 TinyUI入门实践之快速构建个人网站 http://my.oschina.net/tinyframework/blog/348587 Tiny框架 -
Tiny UI on Linux version
2020-11-27 03:07:05<p>The issue is that the game loads and goes into full screen mode but the acual UI is not scaled and is only a small box in the center of the screen. <pre><code> INFO: Julius version 1.1.0.84-a0196aa... -
TinyUI:一个Android UI控件处理库
2019-08-13 15:48:15https://github.com/ddnosh/android-tiny-ui 解决方案 使用view handler去处理每个view的AttributeSet 功能介绍 可以在xml里面设置view的属性; 可以在Java代码里设置view的属性; 用法 <... -
Lutris on HiDPi display has tiny UI
2021-01-10 11:47:55<p>I gave Lutris a shot because of Steam UI which has a same problem on HiDPI displays. <p>While I can still scale to ratio 2 (200%) with the help of <code>export GDK_SCALE=2</code> command, it ... -
Tiny UI changes to the dive list
2020-12-01 11:25:38<p>A few tiny changes to the dive list on desktop. A cleanup and two UI changes. <h3>Changes made: <p>1) Remove an unused function 2) Make the sort order behave more idiomatically (switch to a ... -
Adding a tiny UI element to depictions screen to distinguish from category
2021-01-02 08:27:59We can add some UI element to distinguish it from category screen. <p>My suggestion is displaying a text before user enters any input, saying "We have a new feature to enter depictions, yaaay!...
-
飞秒啁啾脉冲放大系统调节精度的研究
-
Samba 服务配置与管理
-
iPhone消息推送机制实现与探讨
-
五金机械工具箱电商淘宝详情页设计模板.zip
-
2013年下半年 信息系统项目管理师 下午试卷 论文 软考真题【含答案和答案解析】
-
基于python的dango框架购物商城毕业设计毕设源代码使用教程
-
C++代码规范和Doxygen根据注释自动生成手册
-
在电子散斑干涉中利用反相位法进行三维变形测量
-
docker 日常用命令
-
基于电商业务的全链路数据中台落地方案(全渠道、全环节、全流程)
-
MySQL 高可用工具 DRBD 实战部署详解
-
web前端:js-DOM原生轮播图实现解构,js创建标签,js配置样式属性,稳住基础,框架顺手捏来!
-
项目管理工具与方法
-
敏捷软件开发和极限编程介绍
-
家用电钻维修工电工大容量装修工具箱详情页模板.zip
-
高中地理湘教版必修一水循环.docx
-
MySQL 性能优化(思路拓展及实操)
-
井字游戏-源码
-
你不是一个人在战斗-软件项目团队模型
-
2015年上半年 信息系统项目管理师 下午试卷 论文 软考真题【含答案和答案解析】