〇、前言
书接上回(用SquareLine Studio轻松实现ESP8266运行LVGL图形化界面-CSDN博客),用SquareLineStudio导出界面,并通过Arduino下载到esp8266后运行如下:
可是这里的屏幕不是触摸屏,该如何使用屏幕上的button组件呢?
下面使用的代码,是上篇文章中导出的界面代码,这里需要给界面添加可操作性,增加物理按键。
一、物理按键定义
1.1 物理按键引脚连接
这里使用 D0 (GPIO16)和 D1(GPIO5)引脚分别作为【聚焦切换】和【确定】物理按键控制屏幕的2个按钮。
使用下拉电阻方式连接引脚,如图:
1.2 功能定义
如图,给两个物理按键定义功能:
这里举个例子,按下【D0】物理按键,假如选框在【add】按钮组件上,那么再按一下【D1】按键,就会实现value值的增加。再按下【D0】选框在【sub】按钮组件上,那么再按一下【D1】按键,就会实现value值的减少。
注意这里为什么2个物理按键不分别对应【add】按钮和【sub】按钮?
1、如果用这种方式,那么可以用2个物理按键控制更多的按钮组件。
2、lvgl运行后默认聚焦在第一个添加进组的按钮上,如果没有聚焦切换功能按钮,另一个按钮则无法使用。
二、修改代码部分
主要涉及修改的文件就2个,分别是 .\SquareLine_Project\ui\ui.ino 和 .\SquareLine_Project\libraries\ui\src\ui.c文件,下面是修改部分和注释:
2.1 删除部分(可跳过)
因为这里用的屏幕是非触摸屏, SquareLineStudio导出的代码默认是带有触摸部分的,这里不需要,可以删除该部分。下面列出的部分是需要删除的代码(实际这部分不删,也不影响运行)
- ui.ino
cpp
/*Read the touchpad*/
void my_touchpad_read (lv_indev_t * indev_driver, lv_indev_data_t * data) //整个my_touchpad_read函数需要删除掉
{
uint16_t touchX = 0, touchY = 0;
bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );
if (!touched)
{
data->state = LV_INDEV_STATE_REL;
}
else
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touchX;
data->point.y = touchY;
Serial.print( "Data x " );
Serial.println( touchX );
Serial.print( "Data y " );
Serial.println( touchY );
}
}
void setup(){
... ... // 其他部分代码省略
static lv_indev_t* indev; // setup函数中的创建设备的部分, 从这里开始往下4行都删除
indev = lv_indev_create();
lv_indev_set_type( indev, LV_INDEV_TYPE_POINTER );
lv_indev_set_read_cb( indev, my_touchpad_read );
... ...
}
2.2 增加代码
- ui.ino
ui.ino部分主要是增加输入设备组的创建函数和读取按键状态值回调函数,下面是需要增加的代码:
cpp
... ...
lv_group_t *gp; // 新增全局变量gp,用于创建组
... ...
void my_keypad_read(lv_indev_t *indev_driver, lv_indev_data_t *data) // 新增函数my_keypad_read:回调函数用于读取按键状态和按键值
{
if(digitalRead(D0) == HIGH) { // 读取D0是否被按下(实际高低由实际按键接线为准)
data->state = LV_INDEV_STATE_PR; // 定义按键状态是【press/按下】
data->key = LV_KEY_NEXT; // 设置值为LV_KEY_NEXT,D0定义为【聚焦切换】功能按键
}else if(digitalRead(D1) == HIGH){ // 读取D1是否被按下
data->state = LV_INDEV_STATE_PR; // 定义按键状态是【press/按下】
data->key = LV_KEY_ENTER; // 设置值为LV_KEY_ENTER,D0定义为【确定】功能按键
}
else {
data->state = LV_INDEV_STATE_REL; // 定义按键状态是【release/松开】
}
}
void set_button(void){ // 新增set_button函数:创建输入设备组函数
static lv_indev_t* indev;
indev = lv_indev_create(); // 创建一个输入设备
(indev)
lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD); // 该输入设备类型定义为键盘(KEYPAD)
lv_indev_set_read_cb(indev, my_keypad_read); // 键盘绑定回调函数my_keypad_read,回调函数读取键盘状态和按键值
gp = lv_group_create(); // 创建按键组
lv_group_set_default(gp); // 设为默认组(实际开发可能多个设备组,这里就一个组)
lv_group_add_obj(gp, ui_Button1); // 将按键组件1和按键组件2分别加入按键组
lv_group_add_obj(gp, ui_Button2);
lv_indev_set_group(indev, gp); // 将输入设备和按键组绑定。
}
void setup(){
pinMode(D0, INPUT); // 定义为【聚焦切换】按键
pinMode(D1, INPUT); // 定义为【确定】按键
Serial.begin( 115200 );
... ... // 中间省略部分
ui_init();
set_button(); // 一定在ui_init()函数后面调用set_button()函数创建输入设备组,因为按键组件在ui_init()中才被初始化。
Serial.println( "Setup done" );
}
- ui.c
主要是修改按键的事件,根据按键的值实现对应的功能,下面是需要增改的函数
cpp
... ...
void set_focus_obj(void){ //新增函数set_focus_obj,用于切换不同的聚焦组件
lv_obj_t * arr[] = {ui_Button1, ui_Button2}; // 需要循环聚焦的按钮组件列表
static unsigned char index = 0;
lv_group_focus_obj(arr[++index % 2]); // 设置当前需要聚焦的按钮组件
}
void ui_event_Button1(lv_event_t * e) // 修改函数ui_event_Button1:需要修改的按钮1事件函数
{
lv_event_code_t event_code = lv_event_get_code(e); // 获取当前发生的事件
if(event_code == LV_EVENT_KEY) { // 判断是否有按键事件
if(lv_event_get_key(e) == LV_KEY_NEXT){ // 判断是否【聚焦切换】按键按下
set_focus_obj(); // 调用切换聚焦组件函数
}else if(lv_event_get_key(e) == LV_KEY_ENTER) // 判断是否有【确定】键按下
_ui_slider_increment(ui_Slider1, -1, LV_ANIM_ON); // 使slider值加-1,即减1
}
}
void ui_event_Button2(lv_event_t * e) // 修改函数ui_event_Button2:需要修改的按钮2事件函数
{
lv_event_code_t event_code = lv_event_get_code(e); // 获取当前发生的事件
if(event_code == LV_EVENT_KEY) { // 判断是否有按键事件
if(lv_event_get_key(e) == LV_KEY_NEXT){ // 判断是否【聚焦切换】按键按下
set_focus_obj(); // 调用切换聚焦组件函数
}else if(lv_event_get_key(e) == LV_KEY_ENTER){ // 判断是否有【确定】键按下
_ui_slider_increment(ui_Slider1, 1, LV_ANIM_ON); // 使slider值加1,
}
}
}
... ...
三、查看效果
用SquareLine导出esp8266单片机的arduino工程,对其lvgl添加物理按键代码,运行结果呈现