因为要做一个小应用,里面有些参数需要在运行时设置,需要用户在OLED屏上做一些简单的设定,我本想在网上找一些支持菜单开发的库,但找了很久都找不到,在论坛里也只是一些十分简单的例子,全部都是代码写死了菜单,把菜单的显示逻辑、按键响应、菜单的显示样式、菜单的内容完成写成固定的了,我觉得实在有点难看,也不利于之后的再次利用,因此,花了几天的时间写了一个菜单类库。这个库有以下的特点(好象有点自吹自擂了):实现的功能
1.无限制菜单项目、参数项目数量,无限制级联菜单。
2.极简捷菜单项目定义;
3.通过旋转编码器可快速选取菜单项目(可使用两个按键代替旋转编码器);
4.通过旋转编码器可快速调整参数项目值(同上);
5.参数项目的值可以设定为 整数 或 候选列表(返回值也是整数);
6.采用回调函数的方式(类似C#的委托)实现客户化显示,可方便调整成自己需要的显示样式;
7.支持运行期间设定及读取参数项目的值。
8.支持调整菜单时自动触发对应事件,事件与参数项目对应绑定。
9.理论上可支持多种字体,理化上支持中文,但未测试;
10.与u8g2库只是轻度耦合,稍作调整即可切换成其它第三方显示库。

待改进
1.采用C++编写,好像运行效率并无C语言的高。
2.代码量稍多,9KB。
3.运行内存占用稍多。若要同时实现多种功能,建议使用大内存的Arduino板子。

例如,要构建以下的菜单:


Main Menu(主菜单,名字可改)
-menu1 Value-menu11-value111 (参数,整型)
-menu2 Cities-China Cities(参数,列表参数,候选列表内容为 psCitiesChina 。)-USA Cities(参数,列表参数,候选列表内容为 psCitiesUSA 。)
-menu3 Animals-Animal Type (参数,列表参数,候选列表内容为 psAnimals 。)
-MENU4-MENU41-MENU411-MENU4111-MENU41111
-MENU5
-MENU6
-MENU7
-MENU8
-MENU9
-MENU0
-value00(参数,整型)

使用起来的代码如下:

#include "flexmenu.h"
#include "flexmisc.h"
#include <Arduino.h>
#include <U8g2lib.h>U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /*DO clock=*/ 13, /*DI data=*/ 11, /*CS cs=*/ 10, /*DC dc=*/ 9, /* RES reset=*/ 8);TFlexMenu FlexMenu; //我自己写的菜单类
TFlexRotaryEncoder re(2, 3, 4); //我自己写的旋转编码器类,可参看这个贴子:https://www.arduino.cn/thread-86535-1-1.htmlchar *psCitiesChina[6] ={"Beijing", "Shanghai", "Guangzhou", "Shenzhen","Tianjin", "Hangzhou"};
char *psCitiesUSA[4] ={"NewYork", "Manhattan", "Washington", "Seattle"};
char *psAnimals[5] ={"dog", "cat", "mouse", "pig", "cow"};void reRotateEvent(int direct)
{if (direct == -1) FlexMenu.clickUp();if (direct == 1)  FlexMenu.clickDown();
}void Int0Event()
{re.checkState();
}void fmOnDisplayTiltle(char *content, int ttype) //显示标题
{u8g2.setFont(u8g2_font_unifont_t_chinese1);u8g2.drawUTF8(0, 15, content);u8g2.drawLine(0, 16, 128, 16);
}void fmOnDisplayContent(int idx, char *content, int ctype) //显示菜单内容
{if (ctype == 1)  // 需显示的是:一般菜单项{u8g2.drawUTF8(5, (idx + 1) * 16,content);}else if (ctype == 2) //需显示的是:光标指示的一般菜单项{u8g2.drawUTF8(5, (idx + 1) * 16,content);u8g2.drawTriangle(0, 8 + idx * 16, 0, 16 + idx * 16, 4, 12+ idx * 16);}else if (ctype == 3) //需显示的是:待调整的值{int ll = strlen(content) * 8;int sp = (128 - ll) / 2;u8g2.drawUTF8(sp, 3 * 16, content);}
}void fmOnAdjustValueEvent(int id, int value, int upDown)
{String s = "fmOnAdjustValueEvent: id: " + id ;s = s + " value: " + value;s = s + " UpDown: " + upDown;//Serial.println(s);
}void fmOnOKValueEvent(int id, int value)
{// Serial.println("fmOnOKValueEvent: id:%d, value: %d ", id, value);
}void initMenu()
{TFlexMenuItem *mi1, *mi2; // 创建两个临时变量,用于创建层级菜单。//在根菜单下增加一个菜单,名为“menu1 Value”,NULL指的是没有父菜单项目,addMenuItem返回的是增加后该菜单项目的句柄(地址)mi1 = FlexMenu.addMenuItem("menu1 Value", NULL);//在“menu1 Value“菜单下增加一个菜单,名为“menu11”,mi1 传入的是menu1 Value的句柄mi2 = FlexMenu.addMenuItem("menu11", mi1);//增加一个整数型参数,这个参数的名字叫“value111”,id是 1(用于在运行时设置及读取),最大值是 200, 最小值是3,默认值是 100,FlexMenu.addMenuValue(1,"value111", mi2, 100, 200, 3);mi1 = FlexMenu.addMenuItem("menu2 Cities", NULL);//增加一个列表型参数,这个参数的名字叫“China Cities”,id是 2(用于在运行时设置及读取),候选的列表是psCitiesChina,默认是选第1个, 共6个候选值FlexMenu.addMenuValueList(2,"China Cities", mi1, 0, 6, psCitiesChina);//增加一个列表型参数,这个参数的名字叫“USA Cities”,id是 3(用于在运行时设置及读取),候选的列表是psCitiesUSA,默认是选第1个, 共4个候选值FlexMenu.addMenuValueList(3,"USA Cities", mi1, 0, 4, psCitiesUSA);mi1 = FlexMenu.addMenuItem("menu3 Animals", NULL);FlexMenu.addMenuValueList(4,"Animal Type", mi1, 0, 5, psAnimals);mi1 = FlexMenu.addMenuItem("MENU4", NULL);mi1 = FlexMenu.addMenuItem("MENU41", mi1);mi1 = FlexMenu.addMenuItem("MENU411", mi1);mi1 = FlexMenu.addMenuItem("MENU4111", mi1);mi1 = FlexMenu.addMenuItem("MENU41111", mi1);mi1 = FlexMenu.addMenuItem("menu5", NULL);mi1 = FlexMenu.addMenuItem("menu6", NULL);mi1 = FlexMenu.addMenuItem("menu7", NULL);mi1 = FlexMenu.addMenuItem("menu8", NULL);mi1 = FlexMenu.addMenuItem("menu9", NULL);mi1 = FlexMenu.addMenuItem("menu0", NULL);FlexMenu.addMenuValue(100,"value00", NULL, 9, 1000, 3);FlexMenu.init();
}void setup()
{//Serial.begin (9600);FlexMenu.pU8G2 = &u8g2;FlexMenu.pageRow = 3;FlexMenu.attachDisplayTitle(fmOnDisplayTiltle);FlexMenu.attachDisplayContent(fmOnDisplayContent);FlexMenu.attachAdjustValueEvent(fmOnAdjustValueEvent);FlexMenu.attachOKValueEvent(fmOnOKValueEvent);initMenu();re.attachRotateEvent(reRotateEvent);re.setClickResetCount(true);u8g2.begin();attachInterrupt(0, Int0Event, CHANGE);
}void loop()
{FlexMenu.display();if (re.isClick()){ FlexMenu.clickOK();};
}

自制的Arduino多级菜单类相关推荐

  1. 我要做一个蠕动泵的工作记录(二)做一个arduino 多级菜单(2)旋转编码器

    旋转编码器就是这个东西,正转和反转以及按下动作.英文叫Encoder 主要参考文章:https://www.cnblogs.com/watson8544/p/5454086.html,比论文有用多了. ...

  2. c# mvc5 view 多层_MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  3. java递归实现多级菜单栏_Java构建树形菜单以及支持多级菜单的实例代码

    这篇文章主要介绍了Java构建树形菜单的实例代码(支持多级菜单),非常不错,具有参考借鉴价值,需要的朋友可以参考下 效果图:支持多级菜单. 菜单实体类: public class Menu { // ...

  4. 基于STM32的OLED多级菜单GUI实现(简化版智能手表)

    前言:本文的OLED多级菜单UI为一个综合性的STM32小项目,使用多传感器与OLED显示屏实现智能终端的效果.项目中的多级菜单UI使用了较为常见的结构体索引法去实现功能与功能之间的来回切换,搭配DH ...

  5. 12864多级菜单实现方法

    前言        一般来说使用12864进行显示,配合按键作为人机界面交互,如果显示的内容较多的话,往往不能在一个页面显示完全,这里就需要用到多级菜单来进行管理,根据显示内容的不同,将其划分成不同的 ...

  6. STM32简易多级菜单(数组查表法)

    单片机开发中,有时会用到屏幕来显示内容,当需要逐级显示内容时,就需要使用多级菜单的形式了. 1 多级菜单 多级菜单的实现,大体分为两种设计思路: 通过双向链表实现 通过数组查表实现 总体思路都是把菜单 ...

  7. Jeecg使用多级菜单

    基于jeecg3.6.6代码修改,替换ListtoMenu类,或只替换getACESubMenu.getHplusSubMenu和getLeafOfHplusTree三个函数 package org. ...

  8. java 递归查询多级菜单

    类目表是多级目录表,数据如下: 想获取所有数据的多级目录,代码如下: /*** 获取树形接口的 类目** @return*/@Overridepublic List<ExamCategory&g ...

  9. 响应式多级菜单 侧边菜单栏_大菜单,小屏幕:响应式,多级导航

    响应式多级菜单 侧边菜单栏 如果您曾经在响应式网站上工作,那么毫无疑问,您必须解决这个新兴领域中最棘手的问题之一:导航. 对于简单的导航,解决方案可以很简单. 但是,如果您要处理的事情比较复杂,可能有 ...

  10. Java 实现 多级菜单

    一:前言 最近老师布置了给多级菜单的作业,感觉蛮有意思的,可以提升自己的逻辑!下面我写个简易版的多级菜单,本人还是菜鸟,欢迎各位给予宝贵的建议! 二:正文 由于是给各位演示,所有我把涉及的其他条件全省 ...

最新文章

  1. 尴尬!嫌疑人以为警察不懂技术偷删代码,不料被当场识破
  2. 雷林鹏分享:Lua 错误处理
  3. flask 返回html json 并让ios 安卓接收
  4. MongoDB 访问控制
  5. 破解IDEA2018的正确姿势
  6. Flutter实战(一)写一个天气查询的APP
  7. Iptables 入门进阶
  8. 3线程的终止方式,线程属性,NPTL
  9. spark wai_WAI-ARIA对自动完成小部件的支持
  10. java linearlayout_LinearLayout属性用法和源码分析
  11. 机器视觉:偏振镜光学原理和在机器视觉中的应用
  12. 面向深度学习研究人员的自然语言处理实例教程
  13. 2万字总结《MybatisPlus—为简化开发而生》
  14. 三层路由详解、为什么要划分vlan,vlan的作用是什么?
  15. python做人工智能-马哥教育官网-专业Linux培训班,Python培训机构
  16. win10下使用DuetDisplay有线/无线连接,推荐通过爱思助手(非iTunes)更新驱动
  17. 常见概率分布的无记忆性分析
  18. 从新电脑开始构建FATE环境,图文并茂
  19. 猜拳游戏(基于TCP socket的编程)
  20. 1 小时 47 分钟破 1000 亿, 双 11 十周年,你剁手了多少钱?

热门文章

  1. 指纹识别-传感器原理
  2. 判断玩家是否开全图挂
  3. 深度学习经历过程(caffe学习过程)
  4. 数据分析--企业的贤内助 附下载地址
  5. FaceBook到底验证个啥?
  6. gyp ERR! stack Error: Can't find Python executable python, you can set the PYT HON env variable.
  7. LIN、K、CAN、CAN-FD、FlexRay、Ethernet 、MOST、VAN常见汽车总线简介
  8. 华师大 OJ 3036
  9. mysql binlog 回滚_【MySQL】Mysql误操作后使用binlog2sql快速回滚
  10. Internet Explorer之后的前端开发