main.c代码

#include "lvgl/lvgl.h"                  // 包含LVGL核心库头文件
#include "lvgl/demos/lv_demos.h"        // 包含LVGL演示程序头文件
#include "lv_drivers/display/fbdev.h"   // 包含帧缓冲设备驱动头文件
#include "lv_drivers/indev/evdev.h"     // 包含输入设备驱动头文件
#include <unistd.h>                     // 包含UNIX标准函数头文件(如usleep)
#include <pthread.h>                    // 包含线程相关函数头文件
#include <dirent.h>                     // 包含目录操作相关函数头文件
#include <time.h>                       // 包含时间相关函数头文件
#include <sys/time.h>                   // 包含系统时间相关函数头文件
#include <stdio.h>                      // 包含标准输入输出函数头文件
#include <stdlib.h>                     // 包含标准库函数头文件(如malloc)

#define DISP_BUF_SIZE (128 * 1024)      // 定义显示缓冲区大小为128KB
#define BASE_START_OBJ_DIR "/"          // 定义起始目录路径为根目录

typedef struct demo_inf                // 定义演示程序信息结构体
{
    lv_obj_t * main_windows;            // 主窗口对象指针
    lv_obj_t * dir_list;                // 目录列表对象指针
    lv_obj_t * little_windows;          // 右侧小窗口对象指针

}DI,*P_DI;                             // 定义结构体别名及指针别名

struct tmp_inf                         // 定义临时信息结构体(用于事件传递数据)
{
    P_DI p_di;                          // 演示程序信息结构体指针
    char  base_dir_path[256];           // 基础目录路径
};

// 函数声明
P_DI Demo_Init();                                      // 创建主画布并初始化
int  Show_File_List(const char * obj_dir_path,P_DI p_di);  // 显示文件列表
void Close_Img_Btn(lv_event_t *event);                 // 关闭图片按钮回调函数
void Press_Pic_Btn(lv_event_t *event);                 // 点击图片按钮回调函数
void Press_Dir_Btn(lv_event_t *event);                 // 点击目录按钮回调函数

P_DI Demo_Init()                                         // 初始化演示程序界面
{
    P_DI p_di = (P_DI)malloc(sizeof(DI));                // 为演示信息结构体分配内存
    if(p_di == (P_DI)NULL)                               // 检查内存分配是否成功
    {
        perror("malloc ...");                            // 分配失败时输出错误信息
        return (P_DI)-1;                                 // 返回错误值
    }

    memset(p_di,0,sizeof(DI));                           // 初始化结构体内存为0

    p_di->main_windows   = lv_obj_create(NULL);          // 创建主窗口对象(父对象为NULL)

    p_di->dir_list       = lv_list_create(p_di->main_windows);  // 在主窗口上创建目录列表
    
    p_di->little_windows = lv_obj_create(p_di->main_windows);    // 在主窗口上创建右侧小窗口
    

    lv_obj_set_size(p_di->dir_list,300,480);             // 设置左侧目录列表大小(宽300,高480)
    lv_obj_set_size(p_di->little_windows,480,480);       // 设置右侧小窗口大小(宽480,高480)
    lv_obj_set_pos(p_di->dir_list,0,10);                 // 设置目录列表位置(x=0,y=10)
    lv_obj_set_pos(p_di->little_windows,310,10);         // 设置右侧小窗口位置(x=310,y=10)

    lv_scr_load(p_di->main_windows);                     // 将主窗口加载为当前屏幕
    
    return p_di;                                         // 返回演示信息结构体指针
}


void Press_Dir_Btn(lv_event_t *event)                    // 目录按钮点击事件处理函数
{   
    char base_dir_path[256]= "\0";                       // 存储基础目录路径的临时变量
    P_DI p_di = ((struct tmp_inf *)(event->user_data))->p_di;  // 从用户数据中获取演示信息指针
    strcpy(base_dir_path,((struct tmp_inf *)(event->user_data))->base_dir_path);  // 复制目录路径
    
    free(((struct tmp_inf *)(event->user_data)));         // 释放临时信息结构体的内存

    printf("%s\n",base_dir_path);                        // 打印当前目录路径
    


    lv_obj_del(p_di->little_windows);                    // 删除右侧小窗口对象
    lv_obj_del(lv_obj_get_parent(event->current_target)); // 删除当前点击按钮的父对象(列表项)
    printf("+++++----\n");                               // 调试输出
    
    // 重新创建目录列表和右侧窗口
    p_di->dir_list      = lv_list_create(p_di->main_windows);
    p_di->little_windows = lv_obj_create(p_di->main_windows);
    lv_obj_set_size(p_di->dir_list,300,480);             // 重新设置左侧目录列表大小
    lv_obj_set_size(p_di->little_windows,480,480);       // 重新设置右侧小窗口大小
    lv_obj_set_pos(p_di->dir_list,0,10);                 // 重新设置目录列表位置
    lv_obj_set_pos(p_di->little_windows,310,10);         // 重新设置右侧小窗口位置
    Show_File_List(base_dir_path,p_di);                  // 显示新目录下的文件列表

    return ;                                             // 函数返回
}

void Press_Pic_Btn(lv_event_t *event)                    // 图片按钮点击事件处理函数
{
    char base_dir_path[256]= "\0";                       // 存储基础目录路径的临时变量
    P_DI p_di = ((struct tmp_inf *)(event->user_data))->p_di;  // 从用户数据中获取演示信息指针

    // 删掉主界面
    lv_obj_del(p_di->main_windows);                      // 删除主窗口对象
    free(p_di);                                           // 释放演示信息结构体内存


    lv_obj_t * main_draw   = lv_obj_create(NULL);         // 创建新的主画布对象

    lv_obj_t * main_windows   = lv_win_create(main_draw,30);  // 在新画布上创建窗口(边框半径30)
    //lv_obj_set_size(main_windows, LV_HOR_RES, LV_VER_RES);  // 注释:设置窗口大小为屏幕分辨率
    //lv_obj_align(main_windows, LV_ALIGN_CENTER, 0, 0);      // 注释:将窗口居中对齐
    
    lv_obj_t * close_btn      = lv_win_add_btn(main_windows,LV_SYMBOL_CLOSE,30);  // 添加关闭按钮(符号为关闭,大小30)
   
    lv_obj_set_pos(close_btn,450,10);                    // 设置关闭按钮位置(x=450,y=10)
    
    lv_obj_add_event_cb(close_btn,Close_Img_Btn,LV_EVENT_SHORT_CLICKED,main_draw);  // 为关闭按钮添加点击事件回调

    char obj_img_path[256] = "\0";                        // 存储图片路径的变量
    sprintf(obj_img_path,"%s%s","S:",((struct tmp_inf *)(event->user_data))->base_dir_path);  // 拼接图片路径(前缀"S:")
    char * obj_p = &obj_img_path[strlen(obj_img_path)-4];  // 获取文件扩展名(最后4个字符)

    if(strcmp(obj_p,".gif") == 0)                         // 判断文件是否为GIF格式
    {
        // 创建一个图片对象用于显示 GIF 动画
        lv_obj_t *gif_img = lv_gif_create(main_draw);     // 在新画布上创建GIF对象
    
        // 设置 GIF 图片对象的大小模式为正常大小
        lv_img_set_size_mode(gif_img, LV_IMG_SIZE_MODE_REAL);
        // 将 GIF 图片对象居中
        lv_obj_align(gif_img, LV_ALIGN_CENTER, 0, 0);
        lv_gif_set_src(gif_img, obj_img_path);            // 设置 GIF 图片路径
    }
    else                                                   // 非GIF格式图片
    {
        lv_obj_t * img = lv_img_create(main_draw);         // 在画布上创建图像对象
        lv_obj_align(img,LV_ALIGN_CENTER, 0, 0);           // 设置图像居中对齐
        lv_img_set_size_mode(img,LV_IMG_SIZE_MODE_REAL);   // 设置图像大小模式为实际大小
        
        printf("+++%s+++\n",obj_img_path);                 // 打印图片路径(调试用)
        lv_img_set_src(img,obj_img_path);                  // 设置图像的路径
    }

    lv_obj_move_foreground(close_btn);                     // 将关闭按钮置于顶层(避免被图片遮挡)

    lv_scr_load(main_draw);                                // 将新画布加载为当前屏幕
    return;                                                // 函数返回
}

void Close_Img_Btn(lv_event_t *event)                     // 关闭图片按钮事件处理函数
{
    // 删掉图片界面
    lv_obj_del((lv_obj_t *)event->user_data);              // 删除当前图片界面(用户数据为图片界面对象)

    // 重新启动主界面
    P_DI p_di = Demo_Init();                               // 重新初始化演示程序界面
    Show_File_List(BASE_START_OBJ_DIR,p_di);               // 显示起始目录的文件列表

    return ;                                               // 函数返回
}

int  Show_File_List(const char * obj_dir_path,P_DI p_di)   // 显示目录下的文件列表
{
    DIR * dp = opendir(obj_dir_path);                      // 打开指定目录
    if(dp == (DIR *)NULL)                                  // 检查目录是否打开成功
    {
        perror("opendir ... ");                            // 打开失败时输出错误信息
        return -1;                                         // 返回错误值
    }

    char base_path[256];                                   // 存储文件完整路径的变量

    int x=0,y=0;                                           // 右侧小窗口中按钮的坐标变量
    while(1)                                               // 循环读取目录项
    {
        memset(base_path,0,256);                           // 清空路径变量
        
        struct dirent * eq = readdir(dp);                  // 读取目录中的一项
        if(eq == NULL)                                     // 若读取到目录末尾(无更多项)
        {
            break;                                         // 退出循环
        }

        // 拼接完整路径(处理目录路径末尾是否带"/"的情况)
        if(obj_dir_path[strlen(obj_dir_path)-1] == '/')    // 若目录路径以"/"结尾
        {
            sprintf(base_path,"%s%s",obj_dir_path,eq->d_name);  // 直接拼接目录路径和文件名
        }
        else                                               // 若目录路径不以"/"结尾
        {
            sprintf(base_path,"%s/%s",obj_dir_path,eq->d_name); // 拼接目录路径、"/"和文件名
        }

        struct tmp_inf * ti = (struct tmp_inf *)malloc(sizeof(struct tmp_inf));  // 分配临时信息结构体内存
        memset(ti,0,sizeof(struct tmp_inf));               // 初始化临时结构体为0

        strcpy(ti->base_dir_path,base_path);               // 保存文件完整路径到临时结构体

        ti->p_di          = p_di;                          // 保存演示信息结构体指针到临时结构体
        if(eq->d_type == DT_DIR)                            // 判断当前项是否为目录
        {
            // 在目录列表中添加目录按钮(图标为目录符号,文本为目录名)
            lv_obj_t * dir_btn_1 = lv_list_add_btn(p_di->dir_list,LV_SYMBOL_DIRECTORY,eq->d_name);
            // 为目录按钮添加点击事件回调(事件类型为短按,用户数据为临时结构体)
            lv_obj_add_event_cb(dir_btn_1,Press_Dir_Btn,LV_EVENT_SHORT_CLICKED,ti);

        }
        else                                                // 当前项为文件
        {
            // 在目录列表中添加文件按钮(图标为文件符号,文本为文件名)
            lv_obj_t * dir_btn_1 = lv_list_add_btn(p_di->dir_list,LV_SYMBOL_FILE,eq->d_name);
            // 在右侧小窗口中创建按钮
            lv_obj_t * dir_btn_2 = lv_btn_create(p_di->little_windows);
            lv_obj_set_size(dir_btn_2,70,70);              // 设置按钮大小(70x70)
            lv_obj_set_pos(dir_btn_2,x,y);                 // 设置按钮位置
            lv_obj_t *icon = lv_img_create(dir_btn_2);     // 在按钮上创建图标对象
            lv_img_set_src(icon, LV_SYMBOL_OK);            // 设置图标为"OK"符号

            // 在右侧小窗口中创建文件名标签
            lv_obj_t *label = lv_label_create(p_di->little_windows);
            lv_label_set_text(label,eq->d_name);           // 设置标签文本为文件名
            lv_obj_set_pos(label,x,y+75);                  // 设置标签位置(在按钮下方)

            x+=120;                                         // 下一个按钮的x坐标增加120(留出间距)
            if((480-x) <= 70)                               // 若右侧空间不足(小于按钮宽度)
            {
                x = 0;                                      // 重置x坐标为0(换行)
                y+= 100;                                    // y坐标增加100(留出按钮和标签的高度)
            }

            char * obj_p = &eq->d_name[strlen(eq->d_name)-4];  // 获取文件扩展名(最后4个字符)

            // 判断文件是否为图片格式(.bmp/.gif/.jpg/.png)
            if((strcmp(obj_p,".bmp") == 0) || (strcmp(obj_p,".gif") == 0) || (strcmp(obj_p,".jpg") == 0) || (strcmp(obj_p,".png") == 0))
            {
                // 为图片文件按钮添加点击事件回调
                lv_obj_add_event_cb(dir_btn_2,Press_Pic_Btn,LV_EVENT_SHORT_CLICKED,ti);
            }

        }
        

    }

    closedir(dp);                                           // 关闭目录
    return 0;                                                // 函数成功返回
}



int main(void)                                              // 程序主函数
{
    /*LittlevGL init*/
    lv_init();                                               // 初始化LVGL库

    /*Linux frame buffer device init*/
    fbdev_init();                                            // 初始化帧缓冲设备(用于显示)

    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE];                    // 定义显示缓冲区

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;                      // 定义显示缓冲区描述符
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);  // 初始化缓冲区描述符

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;                           // 定义显示驱动结构体
    lv_disp_drv_init(&disp_drv);                             // 初始化显示驱动
    disp_drv.draw_buf   = &disp_buf;                         // 设置驱动使用的缓冲区
    disp_drv.flush_cb   = fbdev_flush;                       // 设置刷新回调函数(帧缓冲刷新)
    disp_drv.hor_res    = 800;                               // 设置水平分辨率为800
    disp_drv.ver_res    = 480;                               // 设置垂直分辨率为480
    lv_disp_drv_register(&disp_drv);                         // 注册显示驱动

    evdev_init();                                            // 初始化输入设备(如触摸屏/鼠标)
    static lv_indev_drv_t indev_drv_1;                       // 定义输入设备驱动结构体
    lv_indev_drv_init(&indev_drv_1);                         // 初始化输入设备驱动
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;                // 设置输入设备类型为指针设备(如鼠标)

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb = evdev_read;                        // 设置输入设备读取回调函数
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);  // 注册输入设备驱动


    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon)                        // 声明鼠标光标图标(LVGL宏)
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act());     // 创建光标图像对象(父对象为当前屏幕)
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);          // 设置光标图像源
    lv_indev_set_cursor(mouse_indev, cursor_obj);            // 将光标图像关联到输入设备


    /*Create a Demo*/
    //lv_demo_widgets();                                      // 注释:使用LVGL自带的部件演示
    P_DI p_di = Demo_Init();                                 // 初始化自定义演示程序

    Show_File_List(BASE_START_OBJ_DIR,p_di);                 // 显示起始目录的文件列表



    /*Handle LitlevGL tasks (tickless mode)*/
    while(1) {                                               //


makefile

#
# Makefile
#
CC = arm-linux-gcc
LVGL_DIR_NAME ?= lvgl
LVGL_DIR ?= ${shell pwd}
CFLAGS ?= -O3 -g0 -I$(LVGL_DIR)/ -Wall -Wshadow -Wundef -Wmissing-prototypes -Wno-discarded-qualifiers -Wall -Wextra -Wno-unused-function -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body -Wtype-limits -Wstack-usage=2048 -Wno-unused-value -Wno-unused-parameter -Wno-missing-field-initializers -Wuninitialized -Wmaybe-uninitialized -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wpointer-arith -Wno-cast-qual -Wmissing-prototypes -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wno-discarded-qualifiers -Wformat-security -Wno-ignored-qualifiers -Wno-sign-compare
LDFLAGS ?= -lm
BIN = demo


#Collect the files to compile
MAINSRC = ./main.c

#include $(LVGL_DIR)/lvgl/lvgl.mk
#include $(LVGL_DIR)/lv_drivers/lv_drivers.mk

CSRCS +=$(LVGL_DIR)/mouse_cursor_icon.c 

OBJEXT ?= .o

AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))

MAINOBJ = $(MAINSRC:.c=$(OBJEXT))

SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
OBJS = $(AOBJS) $(COBJS)

## MAINOBJ -> OBJFILES

all: default

%.o: %.c
	@$(CC)  $(CFLAGS) -c $< -o $@
	@echo "CC $<"
    
default: $(AOBJS) $(COBJS) $(MAINOBJ)
	$(CC) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS) ./liblvgl.so.8.2 -L. -Wall

clean: 
	rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)


还需要上传动态库和生成都demo才可以成功运行:如下


解决图片覆盖返回退出按钮被覆盖的问题改y值就可以了,比如我改了30,就没有覆盖退出按键

更多推荐