跳转至

02 exeasyui单组件演示

作者:沈园园 | 最后修改:2026-04-20

一、概述

本项目是基于 exeasyui 图形用户界面扩展库的完整组件演示程序,展示了 20 种不同的 UI 组件和功能模块。每个演示模块独立运行,通过主程序统一调度管理。

airui 是基于 LVGL 9.4 版本进行图形层封装的 LuatOS 核心库,把常用组件、事件管理、输入和基础视觉主题封装为更易上手的 Lua 接口,便于在支持 LuatOS 的设备和 PC 上统一开发。

建议使用airui来开发显示界面,airui demo参考:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/ui/airui/single

二、演示功能概述

2.1 系统核心模块

1、main.lua - 主程序入口模块

  • 项目初始化和版本定义
  • 系统任务调度和管理
  • 看门狗配置和系统监控
  • 演示模块的选择和加载
  • 提供统一的程序启动入口

2、ui_main.lua - 用户界面主控模块

  • 多页面管理和切换逻辑
  • 触摸事件分发和处理
  • 界面渲染调度
  • 主题管理和配置
  • 提供完整的用户交互体验

3、hw_font_drv.lua - 默认使用字体、lcd显示、tp触摸初始化驱动模块

  • 统一的硬件初始化接口
  • 支持默认字体、HZFont、自定义字体配置
  • LCD显示参数管理
  • 触摸屏配置管理
  • 字体渲染初始化

2.2 基础组件演示

  1. win_label.lua - 动态更新标签演示(实时时间显示,使用默认字体)
  2. win_button.lua - 基础按钮组件演示(使用默认字体)
  3. win_toggle_button.lua - 切换按钮演示(图标切换,使用默认字体)
  4. win_progress_bar.lua - 静态进度条演示(使用默认字体)
  5. win_dyn_progress_bar.lua - 动态进度条演示(自动往复动画,使用默认字体)

2.3 交互组件演示

  1. win_label.lua - 动态更新标签演示(实时时间显示,使用默认字体)
  2. win_button.lua - 基础按钮组件演示(使用默认字体)
  3. win_toggle_button.lua - 切换按钮演示(图标切换,使用默认字体)
  4. win_progress_bar.lua - 静态进度条演示(使用默认字体)
  5. win_dyn_progress_bar.lua - 动态进度条演示(自动往复动画,使用默认字体)

2.4 多媒体组件演示

  1. win_picture.lua - 静态图片显示演示(使用默认字体)
  2. win_autoplay_picture.lua - 自动轮播图片演示(使用默认字体)

2.5 高级功能演示

  1. win_all_component.lua - 所有组件综合演示(带滚动功能,使用默认字体)
  2. win_horizontal_slide.lua - 横向滑动页面演示(使用默认字体)
  3. win_vertical_slide.lua - 纵向滑动页面演示(使用默认字体)
  4. win_switch_page.lua - 页面切换演示(多页面导航,使用默认字体)

2.6 字体渲染演示

  1. win_hzfont.lua - 14 号固件内置矢量字体演示(HzFont)

三、准备硬件环境

1、Air8000核心板 × 1

2、AirLCD_1010 触摸配件板 × 1

3、母对母杜邦线 × 17,杜邦线太长的话,会出现 spi 通信不稳定的现象;

4、TYPE-C 数据线 × 1

5、Air8000核心板和 AirLCD_1010配件板的硬件接线方式为

  • Air8000核心板通过 TYPE-C USB 口供电(核心板背面开关拨到 USB ON 一端 正面开关拨到 供电 一端),此种供电方式下,VDD_EXT 引脚和VBAT为 3.3V,可以直接给 AirLCD_1010配件板供电;
  • 为了演示方便,所以 Air8000核心板上电后直接通过 VDD-EXT引脚给 AirLCD_1010配件板供电;
  • 客户在设计实际项目时,一般来说,需要通过一个 GPIO 来控制 LDO 给配件板供电,这样可以灵活地控制配件板的供电,可以使项目的整体功耗降到最低;

LCD 显示屏接线

Air8000核心板 AirLCD_1010配件板
LCD_CLK SCLK/CLK
LCD_CS CS
LCD_RST RES/RST
LCD_SDA SDA/MOS
LCD_RS DC/RS
GPIO1 BLK
VDD_EXT VCC
I2C1_SCL SCL
I2C1_SDA SDA
WAKEUP0 INT
GND GND

四、准备软件环境

4.1 软件环境

在开始实践本示例之前,先筹备一下软件环境:

1、烧录工具:Luatools 下载调试工具

2、内核固件:本demo开发测试时使用的固件为LuatOS-SoC_V2018_Air8000 1号固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;

使用 HZfont 需要使用 V2020 版本以上的 14 号固件或114号固件,且 14 号固件或114号固件仅支持 HZfont

使用其他字体,demo 所使用的是 LuatOS-SoC_V2018 1 号固件

3、脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/ui/easyui/single

4、lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件

准备好软件环境之后,接下来查看如何烧录项目文件到Air8000核心板,将本篇文章中演示使用的项目文件烧录到Air8000核心板中。

4.2 API 介绍

exeasyui UI扩展库:https://docs.openluat.com/osapi/ext/exeasyui/

五、程序结构

ui/easyui/single
│── main.lua
│── images                    
    │── xxx.jpg                 
│── hw_font_drv.lua
│── win_all_component.lua
│── win_autoplay_picture.lua
│── win_button.lua
│── win_check_box.lua
│── win_combo_box.lua
│── win_dyn_progress_bar.lua
│── win_horizontal_slide.lua
│── win_input.lua
│── win_label.lua
│── win_message_box.lua
│── win_number_input.lua
│── win_password_input.lua
│── win_picture.lua
│── win_progress_bar.lua
│── win_switch_page.lua
│── win_toggle_button.lua
│── win_vertical_slide.lua
│── win_hzfont.lua
│── readme.md

5.1 文件说明

1、main.lua:整个项目的入口点。它负责初始化系统环境

2、images

  • xxx.jpg:演示图片文件(和lua脚本文件一起烧录,会自动放置在/luadb/目录下)

3、hw_font_drv.lua:默认使用字体、lcd显示、tp触摸初始化驱动模块

4、win_all_component.lua:所有组件综合演示(带滚动功能,使用默认字体)

5、win_autoplay_picture.lua:自动轮播图片演示(使用默认字体)

6、win_button.lua:基础按钮组件演示(使用默认字体)

7、win_check_box.lua:复选框组件演示(使用默认字体)

8、win_combo_box.lua:下拉框组件演示(使用默认字体)

9、win_dyn_progress_bar.lua:动态进度条演示(自动往复动画,使用默认12号英文点阵字体)

10、win_horizontal_slide.lua:横向滑动页面演示(使用默认字体)

11、win_input.lua:文本输入框演示(使用默认字体)

12、win_label.lua:动态更新标签演示(实时时间显示,使用默认字体)

13、win_message_box.lua:消息框组件演示(使用默认字体)

14、win_number_input.lua:数字输入框演示(带增减按钮,使用默认字体)

15、win_password_input.lua:密码输入框演示(带显示/隐藏切换,使用默认字体)

16、win_picture.lua:静态图片显示演示(使用默认字体)

17、win_progress_bar.lua:静态进度条演示(使用默认字体)

18、win_switch_page.lua:页面切换演示(多页面导航,使用默认字体)

19、win_toggle_button.lua:切换按钮演示(图标切换,使用默认字体)

20、win_vertical_slide.lua:纵向滑动页面演示(使用默认字体)

21、win_hzfont.lua:14 号固件内置矢量字体演示(HzFont)

六、代码详解

6.1 main.lua

主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。

6.2 hw_font_drv.lua

本文件为字体驱动配置模块,核心业务逻辑为:

1、配置LCD显示和触摸屏参数;

2、提供统一的硬件初始化接口;

local hw_font_drv = {}

-- 硬件配置参数
local hw_config = {
    -- lcd_config参数填写可以参考合宙exlcd显示扩展库exlcd.init(param)接口说明:https://docs.openluat.com/osapi/ext/exlcd/#31-exlcdinitparam
    lcd_config = {
        lcd_model = "AirLCD_1010", -- LCD型号
        -- pin_vcc = 24,           -- 供电引脚,使用GPIO控制屏幕供电可配置
        pin_rst = 36,              -- 复位引脚
        pin_pwr = 1,               -- 背光控制引脚GPIO ID号
        pin_pwm = 0,               -- 背光控制引脚PWM ID号
        port = lcd.HWID_0,         -- 驱动端口
        -- pin_dc = 0xFF,          -- lcd数据/命令选择引脚GPIO ID号,使用lcd 专用 SPI 接口 lcd.HWID_0不需要填此参数,使用通用SPI接口需要赋值
        direction = 0,             -- lcd屏幕方向 0:0° 1:90° 2:180° 3:270°,屏幕方向和分辨率保存一致
        w = 320,                   -- lcd 水平分辨率
        h = 480,                   -- lcd 竖直分辨率
        xoffset = 0,               -- x偏移(不同屏幕ic 不同屏幕方向会有差异)
        yoffset = 0,               -- y偏移(不同屏幕ic 不同屏幕方向会有差异)
        sleepcmd = 0X10,           -- 睡眠命令,默认0X10
        wakecmd = 0X11,            -- 唤醒命令,默认0X11
        -- bus_speed = 50*1000*1000,                            -- SPI总线速度,不填默认50M,若速率要求更高需要进行设置
        -- interface_mode = lcd.WIRE_4_BIT_8_INTERFACE_I,       -- lcd模式,默认lcd.WIRE_4_BIT_8_INTERFACE_I
        -- direction0 = {0x36,0x00},                            -- 0°方向的命令,(不同屏幕ic会有差异)
        -- direction90 = {0x36,0x60},                           -- 90°方向的命令,(不同屏幕ic会有差异)
        -- direction180 ={0x36,0xc0} ,                          -- 180°方向的命令,(不同屏幕ic会有差异)
        -- direction270 = {0x36,0xA0},                          -- 270°方向的命令,(不同屏幕ic会有差异)
        -- hbp = nil,                                           -- 水平后廊
        -- hspw = nil,                                          -- 水平同步脉冲宽度
        -- hfp = 0,                                             -- 水平前廊
        -- vbp = 0,                                             -- 垂直后廊
        -- vspw = 0,                                            -- 垂直同步脉冲宽度
        -- vfp = 0,                                             -- 垂直前廊
        -- initcmd = nil,                                       -- 自定义屏幕初始化命令表
        -- flush_rate = nil,                                    -- 刷新率
        -- spi_dev = nil,                                       -- spi设备,当port = "device"时有效,当port ≠ "device"时可不填或者填nil
        -- init_in_service = false,                             -- 允许初始化在lcd service里运行,在后台初始化LCD,默认是false,Air8000/G/W/T/A、Air780EHM/EGH/EHV 支持填true,可加快初始化速度,默认SPI总线速度80M
    },

    -- tp_config参数填写可以参考合宙extp触摸扩展库以下三个接口说明:https://docs.openluat.com/osapi/ext/extp/#41-extpinitparam
    -- 按extp.init(param)接口说明填写tp_model、i2c_id、pin_rst、pin_int参数
    -- 按extp.set_publish_enabled(msg_type, enabled)接口说明和实际需求填写message_enabled{}列表内参数
    -- 按extp.set_swipe_threshold(threshold)接口说明填写swipe_threshold和long_press_threshold参数
    tp_config = {
        tp_model = "AirLCD_1010", -- 触摸芯片/设备型号
        i2c_id = 1,               -- I2C总线ID
        pin_rst = 0xFF,           -- 触摸芯片复位引脚(AirLCD_1010上没有引出该引脚)
        pin_int = gpio.WAKEUP0,             -- 触摸芯片中断引脚
        -- @param message_enabled 消息类型 ("ALL", "RAW_DATA", "TOUCH_DOWN", "MOVE_X", "MOVE_Y", "SWIPE_LEFT", "SWIPE_RIGHT", "SWIPE_UP", "SWIPE_DOWN", "SINGLE_TAP", "LONG_PRESS")
        message_enabled = {
            TOUCH_DOWN = true,      -- 启用按下检测
            MOVE_X = true,          -- 启用横向滑动
            MOVE_Y = true,          -- 启用纵向滑动
            SWIPE_LEFT = true,      -- 启用左滑手势
            SWIPE_RIGHT = true,     -- 启用右滑手势
            SWIPE_UP = true,        -- 启用上滑手势
            SWIPE_DOWN = true,      -- 启用下滑手势
            SINGLE_TAP = true,      -- 启用点击手势
            LONG_PRESS = false      -- 禁用长按手势
        },
        swipe_threshold = 10,       -- 设置滑动阈值
        long_press_threshold = 2000 -- 设置长按阈值(毫秒)
    }
}

function hw_font_drv.init(font_config)
    -- 如果有字体配置,则添加到硬件配置中
    if font_config then
        hw_config.font_config = font_config
    end

    -- 初始化硬件
    ui.hw_init(hw_config)

    log.info("hw_font_drv", "硬件初始化完成", font_config and "使用字体配置" or "使用默认字体")
end

return hw_font_drv

6.3 win_all_component.lua

本文件为所有UI组件综合演示模块,核心业务逻辑为:

1、创建带滚动功能的窗口容器;

2、集成展示所有exEasyUI组件;

3、实现组件间的交互逻辑;

4、展示进度条、消息框、按钮、复选框、输入框等完整功能;

5、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器并启用滚动
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })
    page1:enable_scroll({
        direction = "vertical",
        content_height = 1000,
        threshold = 8
    })

    -- ==================== 标题区域 ====================
    local title = ui.label({
        x = 100, y = 25,
        text = "组件演示页面",
        color = ui.COLOR_BLACK,
        size = 16
    })
    page1:add(title)

    -- ==================== 进度条组件区域 ====================
    local progress_label = ui.label({
        x = 20, y = 70,
        text = "1. 进度条组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local progress = 0
    local pb = ui.progress_bar({
        x = 20, y = 100,
        w = 200, h = 26,
        progress = progress
    })

    local btn_progress = ui.button({
        x = 230, y = 100,
        w = 70, h = 26,
        text = "+10%",
        on_click = function(self)
            progress = progress + 10
            if progress > 100 then
                progress = 0
            end
            pb:set_progress(progress)
            pb:set_text("进度: " .. progress .. "%")
        end
    })

    page1:add(progress_label)
    page1:add(pb)
    page1:add(btn_progress)

    -- ==================== 消息框组件区域 ====================
    local msgbox_label = ui.label({
        x = 20, y = 140,
        text = "2. 消息框组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local btn_msgbox = ui.button({
        x = 20, y = 170,
        w = 120, h = 30,
        text = "弹出消息框",
        on_click = function(self)
            local message_box = ui.message_box({
                x = 40, y = 150,
                w = 240, h = 180,
                wordWrap = true,
                title = "祝福",
                message = "愿你前路浩荡,未来可期.愿你保持热爱,奔赴山海。愿你所有的努力都不被辜负,最终活成自己最喜欢的模样.加油!",
                buttons = { "接受祝福" }
            })
            ui.add(message_box)
        end
    })

    page1:add(msgbox_label)
    page1:add(btn_msgbox)

    -- ==================== 切换按钮组件区域 ====================
    local toggle_label = ui.label({
        x = 20, y = 220,
        text = "3. 切换按钮演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local btn_toggle = ui.button({
        x = 20, y = 250,
        w = 64, h = 64,
        src = "/luadb/4.jpg",
        src_toggled = "/luadb/5.jpg",
        toggle = true,
    })

    page1:add(toggle_label)
    page1:add(btn_toggle)

    -- ==================== 复选框组件区域 ====================
    local checkbox_label = ui.label({
        x = 20, y = 330,
        text = "4. 复选框组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local checkbox1 = ui.check_box({
        x = 20, y = 360,
        text = "选项A",
        checked = false,
        on_change = function(checked)
            log.info("checkbox", "选项A:", checked)
        end
    })

    local checkbox2 = ui.check_box({
        x = 120, y = 360,
        text = "选项B",
        checked = true,
        on_change = function(checked)
            log.info("checkbox", "选项B:", checked)
        end
    })

    page1:add(checkbox_label)
    page1:add(checkbox1)
    page1:add(checkbox2)

    -- ==================== 输入框组件区域 ====================
    local input_label = ui.label({
        x = 20, y = 410,
        text = "5. 输入框组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local text_input = ui.input({
        x = 20, y = 440,
        w = 200, h = 30,
        placeholder = "请输入文本...",
        max_length = 20
    })

    page1:add(input_label)
    page1:add(text_input)

    -- ==================== 密码输入框组件区域 ====================
    local password_label = ui.label({
        x = 20, y = 490,
        text = "6. 密码输入框演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local password_input = ui.input({
        x = 20, y = 520,
        w = 150, h = 30,
        placeholder = "请输入密码...",
        input_type = "password",
        max_length = 16
    })

    local password_visible = false
    local btn_password_toggle = ui.button({
        x = 180, y = 520,
        w = 60, h = 30,
        text = "显示",
        bg_color = ui.COLOR_BLUE,
        text_color = ui.COLOR_WHITE,
        on_click = function()
            password_visible = not password_visible
            password_input.input_type = password_visible and "text" or "password"
            btn_password_toggle:set_text(password_visible and "隐藏" or "显示")
        end
    })

    page1:add(password_label)
    page1:add(password_input)
    page1:add(btn_password_toggle)

    -- ==================== 数字输入框组件区域 ====================
    local number_label = ui.label({
        x = 20, y = 570,
        text = "7. 数字输入框演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local number_input = ui.input({
        x = 20, y = 600,
        w = 100, h = 30,
        placeholder = "0-100",
        input_type = "number",
        max_length = 3
    })

    local btn_number_minus = ui.button({
        x = 130, y = 600,
        w = 40, h = 30,
        text = "-",
        on_click = function()
            local value = tonumber(number_input:get_text()) or 0
            if value > 0 then
                number_input:set_text(tostring(value - 1))
            end
        end
    })

    local btn_number_plus = ui.button({
        x = 180, y = 600,
        w = 40, h = 30,
        text = "+",
        on_click = function()
            local value = tonumber(number_input:get_text()) or 0
            if value < 100 then
                number_input:set_text(tostring(value + 1))
            end
        end
    })

    page1:add(number_label)
    page1:add(number_input)
    page1:add(btn_number_minus)
    page1:add(btn_number_plus)

    -- ==================== 下拉框组件区域 ====================
    local combo_label = ui.label({
        x = 20, y = 650,
        text = "8. 下拉框组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local combo_box = ui.combo_box({
        x = 20, y = 680,
        w = 200, h = 30,
        options = { "选项1", "选项2", "选项3" },
        placeholder = "请选择",
        selected = 1,
        on_select = function(value, index, text)
            log.info("combo_box", "选择了:", text, "索引:", index)
        end
    })

    page1:add(combo_label)
    page1:add(combo_box)

    -- ==================== 图片轮播组件区域 ====================
    local picture_label = ui.label({
        x = 20, y = 730,
        text = "9. 图片自动轮播组件演示:",
        color = ui.COLOR_BLACK,
        size = 14
    })

    local pic = ui.picture({
        x = 20, y = 760,
        w = 128, h = 128,
        sources = { "/luadb/1.jpg", "/luadb/2.jpg", "/luadb/3.jpg" },
        autoplay = true,
        interval = 1500
    })

    local btn_picture_toggle = ui.button({
        x = 160, y = 760,
        w = 80, h = 30,
        text = "手动切换图片",
        on_click = function()
            pic:next()
        end
    })

    page1:add(picture_label)
    page1:add(pic)
    page1:add(btn_picture_toggle)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.4 win_autoplay_picture.lua

本文件为自动轮播图片演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加图片轮播组件;

3、配置自动播放和切换间隔;

4、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建自动轮播图片组件
    local pic = ui.picture({ 
        x = 20, y = 20, 
        sources = {"/luadb/1.jpg", "/luadb/2.jpg", "/luadb/3.jpg"}, 
        autoplay = true, 
        interval = 1500
    })

    -- 添加组件到窗口
    page1:add(pic)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.5 win_button.lua

本文件为基础按钮组件演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加基础按钮组件;

3、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建按钮组件(文本模式)
    local btn1 = ui.button({ x = 20, y = 20, text = "基础按钮" })

    -- 添加组件到窗口
    page1:add(btn1)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.6 win_check_box.lua

本文件为复选框组件演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加复选框组件;

3、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建复选框组件
    local cb = ui.check_box({ 
        x = 20, y = 20, 
        text = "Check me"
    })

    -- 添加组件到窗口
    page1:add(cb)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.7 win_combo_box.lua

本文件为下拉框组件演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加下拉框组件;

3、配置选项列表和选择回调;

4、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建下拉框组件
    local combo_box = ui.combo_box({
        x = 20, y = 20,
        w = 200, h = 30,
        options = { "选项1", "选项2", "选项3" },
        placeholder = "请选择",
        selected = 1,
        on_select = function(value, index, text)
            log.info("component_page", "选择了:", text, "索引:", index)
        end
    })

    -- 添加组件到窗口
    page1:add(combo_box)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.8 win_dyn_progress_bar.lua

本文件为动态进度条演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加进度条组件;

3、在主循环中动态更新进度条数值;

4、实现进度条往复动画效果;

5、启动UI渲染循环持续刷新显示;

local direction = 1 
local current = 0

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建进度条组件
    local pb = ui.progress_bar({ 
        x = 20, y = 20, 
        w = 280, h = 26
    })

    -- 添加组件到窗口
    page1:add(pb)

    -- 注册窗口到UI系统
    ui.add(page1)

    -- 启动exeasyui刷新主循环
    while true do
        -- 动态更新进度条数值
        current = current + direction
        if current >= 100 then
            direction = -1
        elseif current <= 0 then
            direction = 1
        end

        pb:set_progress(current)

        -- 等待30ms
        sys.wait(30)
    end
end

sys.taskInit(ui_main)

6.9 win_horizontal_slide.lua

本文件为横向滑动页面演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、启用横向滑动功能;

3、创建两页内容并水平排列;

4、实现横向滑动切换页面效果;

5、启动UI渲染循环持续刷新显示;

local function ui_main()
    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local win = ui.window({ background_color = ui.COLOR_WHITE })

    -- 启用横向滚动,将两页内容并排布置
    local page_w, page_h = lcd.getSize()
    local totalW = page_w * 2

    -- 创建横向滑动窗口
    win:enable_scroll({
        direction = "horizontal",
        content_width = totalW,
        threshold = 8,
        page_width = page_w
    })

    -- 创建网格按钮函数
    local function makeGrid(offset_x, label_prefix)
        local cols, rows = 3, 3
        local bw, bh = 90, 80
        local mx, my = 20 + offset_x, 60
        local gapx, gapy = 10, 10
        local n = 1
        for r = 0, rows - 1 do
            for c = 0, cols - 1 do
                local x = mx + c * (bw + gapx)
                local y = my + r * (bh + gapy)
                local btn = ui.button({
                    x = x,
                    y = y,
                    w = bw,
                    h = bh,
                    text = string.format("%s-%d", label_prefix, n)
                })
                win:add(btn)
                n = n + 1
            end
        end
    end

    -- 创建左页和右页内容
    makeGrid(0, "P1")      -- 第一页
    makeGrid(page_w, "P2") -- 第二页

    -- 注册窗口到UI系统
    ui.add(win)

end

sys.taskInit(ui_main)

6.10 win_input.lua

本文件为文本输入框演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加文本输入框组件;

3、设置占位符文本和最大长度限制;

4、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建文本输入框组件
    local text_input = ui.input({
        x = 20, y = 20,
        w = 200, h = 30,
        placeholder = "请输入文本...",
        max_length = 20
    })

    -- 添加组件到窗口
    page1:add(text_input)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.11 win_label.lua

本文件为基础标签组件演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加静态标签组件显示"hello exEasyUI"文本;

3、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建标签组件
    local lbl = ui.label({ x = 20, y = 20, text = "hello exEasyUI"})

    -- 添加组件到窗口
    page1:add(lbl)

    -- 注册窗口到UI系统
    ui.add(page1)

    -- 循环刷新时间
    while true do
        -- 更新时间给文本组件lbl
        lbl:set_text("时间:"..os.date("%Y-%m-%d %H:%M:%S"))

        -- 等待300ms
        sys.wait(300)
    end

end

sys.taskInit(ui_main)

6.12 win_message_box.lua

本文件为消息框组件演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加消息框组件显示通知信息;

3、启用自动换行功能显示长文本;

4、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建消息框组件
    local box = ui.message_box({ 
        x = 20, y = 20, 
        wordWrap = true,
        title = "通知", 
        message = "愿你前路浩荡,未来可期.愿你保持热爱,奔赴山海。愿你所有的努力都不被辜负,最终活成自己最喜欢的模样.加油!"
    })

    -- 添加组件到窗口
    page1:add(box)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.13 win_number_input.lua

本文件为数字输入框演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加数字输入框组件;

3、添加增减按钮控制数字输入;

4、实现数字范围限制功能;

5、启动UI渲染循环持续刷新显示;

local function ui_main()  

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建数字输入框组件
    local number_input = ui.input({
        x = 20, y = 20,
        w = 100, h = 30,
        placeholder = "0-100",
        input_type = "number",
        max_length = 3
    })

    -- 创建减少按钮
    local btn_number_minus = ui.button({
        x = 130, y = 20,
        w = 40, h = 30,
        text = "-",
        on_click = function()
            local value = tonumber(number_input:get_text()) or 0
            if value > 0 then
                number_input:set_text(tostring(value - 1))
            end
        end
    })

    -- 创建增加按钮
    local btn_number_plus = ui.button({
        x = 180, y = 20,
        w = 40, h = 30,
        text = "+",
        on_click = function()
            local value = tonumber(number_input:get_text()) or 0
            if value < 100 then
                number_input:set_text(tostring(value + 1))
            end
        end
    })

    -- 添加组件到窗口
    page1:add(number_input)
    page1:add(btn_number_minus)
    page1:add(btn_number_plus)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.14 win_password_input.lua

本文件为密码输入框演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加密码输入框组件;

3、添加显示/隐藏密码切换按钮;

4、实现密码可见性切换功能;

5、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建密码输入框组件
    local password_input = ui.input({
        x = 20, y = 20,
        w = 150, h = 30,
        placeholder = "请输入密码...",
        input_type = "password",
        max_length = 16
    })

    -- 创建密码显示/隐藏切换按钮
    local password_visible = false
    local btn_password_toggle = ui.button({
        x = 180, y = 20,
        w = 60, h = 30,
        text = "显示",
        bg_color = ui.COLOR_BLUE,
        text_color = ui.COLOR_WHITE,
        on_click = function()
            password_visible = not password_visible
            password_input.input_type = password_visible and "text" or "password"
            btn_password_toggle:set_text(password_visible and "隐藏" or "显示")
        end
    })

    -- 添加组件到窗口
    page1:add(password_input)
    page1:add(btn_password_toggle)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.15 win_picture.lua

本文件为静态图片显示演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加静态图片显示组件;

3、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建静态图片组件
    local pic = ui.picture({ 
        x = 20, y = 20, 
        sources = {"/luadb/logo.jpg"}
    })

    -- 添加组件到窗口
    page1:add(pic)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.16 win_progress_bar.lua

本文件为静态进度条演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加静态进度条组件;

3、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建进度条组件
    local pb = ui.progress_bar({ 
        x = 20, y = 20, 
        w = 280, h = 26
    })

    -- 添加组件到窗口
    page1:add(pb)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.17 win_switch_page.lua

本文件为页面切换演示模块,核心业务逻辑为:

1、创建主页面窗口容器;

2、配置多个子页面工厂函数;

3、实现页面间切换导航功能;

4、演示消息框页面和复选框页面;

5、实现子页面销毁和内存管理;

6、启动UI渲染循环持续刷新显示;

-- 创建消息框演示页面
local function msgbox_page()
    local win = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建页面标题(使用无按钮的消息框)
    local title = ui.message_box({ 
        x = 10, y = 10,
        w = 300, h = 80,
        title = "消息框页面",
        message = "点击按钮弹出消息框",
        buttons = {}  -- 空按钮数组,不显示按钮
    })

    -- 创建"弹出消息框"按钮
    local btn = ui.button({
        x = 20, y = 140,
        w = 180, h = 50,
        text = "弹出消息框",
        on_click = function()
            -- 创建消息框
            local box = ui.message_box({
                x = 40, y = 210,
                w = 240, h = 120,
                title = "提示",
                message = "这是一条消息",
                buttons = { "确定", "取消" },
                on_result = function()
                    -- 处理按钮点击逻辑
                end
            })
            ui.add(box)
        end
    })

    -- 创建"返回"按钮
    local back = ui.button({
        x = 220, y = 140,
        w = 80, h = 50,
        text = "返回",
        on_click = function()
            win:back()  -- 返回主页
        end
    })

    -- 添加组件到窗口
    win:add(title)
    win:add(btn)
    win:add(back)

    return win
end

-- 创建复选框演示页面
local function check_box_page()
    local win = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建页面标题
    local title = ui.message_box({ 
        x = 10, y = 10,
        w = 300, h = 80,
        title = "复选框页面", 
        message = "演示多个check_box", 
        buttons = {} 
    })

    -- 创建三个复选框
    local cb1 = ui.check_box({ x = 20, y = 120, text = "选项A" })
    local cb2 = ui.check_box({ x = 20, y = 160, text = "选项B", checked = true })
    local cb3 = ui.check_box({ x = 20, y = 200, text = "选项C" })

    -- 创建返回按钮
    local back = ui.button({
        x = 20, y = 260,
        w = 120, h = 40,
        text = "返回主页",
        on_click = function()
            win:back()
        end
    })

    -- 添加组件到窗口
    win:add(title)
    win:add(cb1)
    win:add(cb2)
    win:add(cb3)
    win:add(back)

    return win
end

-- 主程序入口函数
local function ui_main()


    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建主页面
    local home = ui.window({ background_color = ui.COLOR_WHITE })

    -- 配置子页面工厂函数
    home:configure_subpages({ 
        page1 = msgbox_page,   -- 消息框演示页面
        page2 = check_box_page  -- 复选框演示页面
    })

    -- 创建导航按钮1:进入复选框示例页面
    local btn1 = ui.button({
        x = 20, y = 60,
        w = 280, h = 50,
        text = "复选框示例",
        on_click = function()
            home:show_subpage("page2")
        end
    })

    -- 创建导航按钮2:进入消息框示例页面  
    local btn2 = ui.button({
        x = 20, y = 130,
        w = 280, h = 50,
        text = "消息框示例",
        on_click = function()
            home:show_subpage("page1")
        end
    })

    -- 创建功能按钮:移除复选框子界面(演示销毁功能)
    local btnRemove = ui.button({
        x = 20, y = 200,
        w = 280, h = 50,
        text = "移除复选框子界面(销毁)",
        on_click = function()
            -- 强制销毁缓存的check_box子页面,释放内存
            home:close_subpage("page2", { destroy = true })
        end
    })

    -- 添加按钮到主页面
    home:add(btn1)
    home:add(btn2)
    home:add(btnRemove)

    -- 注册主页面到UI系统
    ui.add(home)

end

sys.taskInit(ui_main)

6.18 win_toggle_button.lua

本文件为切换按钮演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、添加图标模式切换按钮组件;

3、实现按钮点击切换图片功能;

4、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local page1 = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建切换按钮组件(图标模式)
    local btn2 = ui.button({
        x = 20, y = 20, 
        w = 64, h = 64,
        toggle = true,                  -- 启用切换模式
        src = "/luadb/4.jpg",           -- 默认图片
        src_toggled = "/luadb/5.jpg",   -- 切换状态时的图片
    })

    -- 添加组件到窗口
    page1:add(btn2)

    -- 注册窗口到UI系统
    ui.add(page1)

end

sys.taskInit(ui_main)

6.19 win_vertical_slide.lua

本文件为纵向滑动页面演示模块,核心业务逻辑为:

1、创建窗口容器并设置白色背景;

2、启用纵向滑动功能;

3、创建两页内容并垂直排列;

4、实现纵向滑动切换页面效果;

5、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 显示触摸初始化
    hw_font_drv.init()

    -- 设置主题
    ui.sw_init({ theme = "light" })

    -- 创建窗口容器
    local win = ui.window({ background_color = ui.COLOR_WHITE })

    -- 启用纵向分页滚动,将两页内容上下排布
    local page_w, page_h = lcd.getSize()
    local total_h = page_h * 2

    -- 创建纵向滑动窗口
    win:enable_scroll({ 
        direction = "vertical", 
        content_height = total_h, 
        threshold = 10, 
        page_height = page_h 
    })

    -- 创建按钮布局函数
    local function makebuttons(offset_y, label_prefix)
        -- 竖直等间距排列:1列3行,水平居中
        local cols, rows = 1, 3
        local bw, bh = 90, 80
        local mx = math.floor((page_w - bw) / 2) -- 居中
        local gap = math.floor((page_h - rows * bh) / (rows + 1))
        if gap < 8 then gap = 8 end
        local n = 1
        for r = 0, rows - 1 do
            local x = mx
            local y = offset_y + gap + r * (bh + gap)
            local btn = ui.button({ 
                x = x, y = y, 
                w = bw, h = bh, 
                text = string.format("%s-%d", label_prefix, n) 
            })
            win:add(btn)
            n = n + 1
        end
    end

    -- 创建上页和下页内容
    makebuttons(0, "P1")  -- 第一页
    makebuttons(page_h, "P2")  -- 第二页

    -- 注册窗口到UI系统
    ui.add(win)

end

sys.taskInit(ui_main)

6.20 win_hzfont.lua

本文件为HzFont矢量字体演示模块,核心业务逻辑为:

1、启用14号固件内置HzFont矢量字体方式驱动;

2、创建窗口容器并设置白色背景;

3、添加多个标签组件展示矢量字体特性;

4、演示抗锯齿渲染和智能缓存功能;

5、启动UI渲染循环持续刷新显示;

local function ui_main()

    -- 启用14号固件内置HzFont矢量字体方式驱动
    hw_font_drv.init({
        type = "hzfont",
        size = 32,
        antialias = -1  -- 自动抗锯齿
    })

    -- 设置主题
    ui.init({ theme = "light" })

    -- 创建窗口容器
    local win = ui.window({ background_color = ui.COLOR_WHITE })

    -- 创建多个标签展示矢量字体特性
    local text1 = ui.label({ x = 10, y = 20, text = "HzFont矢量字体", color = ui.COLOR_BLACK })
    local text2 = ui.label({ x = 10, y = 60, text = "Hello World", color = ui.COLOR_RED })
    local text3 = ui.label({ x = 10, y = 100, text = "支持10-100号大小", color = ui.COLOR_GREEN })
    local text4 = ui.label({ x = 10, y = 140, text = "支持抗锯齿渲染", color = ui.COLOR_BLUE })
    local text5 = ui.label({ x = 10, y = 180, text = "智能缓存加速", color = ui.COLOR_ORANGE })

    -- 添加组件到窗口
    win:add(text1)
    win:add(text2)
    win:add(text3)
    win:add(text4)
    win:add(text5)

    -- 注册窗口到UI系统
    ui.add(win)

end

sys.taskInit(ui_main)

七、显示效果展示

7.1 硬件准备

  1. 按照硬件接线表连接所有设备
  2. 通过 TYPE-C USB 口供电
  3. 检查所有接线无误

7.2 软件配置

main.lua 中选择要运行的演示模块:

-- 必须加载才能启用exeasyui的功能
ui = require("exeasyui")

-- 加载显示触摸和字体驱动模块
hw_font_drv = require("hw_font_drv")

-- 引入演示模块
-- 使用哪个加载哪个每次选择加载一个
-- require("win_label") --动态更新标签演示
-- require("win_button")  --基础按钮组件演示
-- require("win_toggle_button")  --切换按钮演示
-- require("win_progress_bar")  --静态进度条演示
-- require("win_dyn_progress_bar")  --动态进度条演示
-- require("win_message_box")  --消息框组件演示
-- require("win_check_box")  --复选框组件演示
-- require("win_picture")  --静态图片显示演示
-- require("win_autoplay_picture")  --自动轮播图片演示
-- require("win_combo_box")  --下拉框组件演示
-- require("win_input")  --文本输入框演示
-- require("win_password_input")  --密码输入框演示
-- require("win_number_input")  --数字输入框演示
require("win_all_component")  --所有组件综合演示
-- require("win_horizontal_slide")  --横向滑动页面演示
-- require("win_vertical_slide")  --纵向滑动页面演示
-- require("win_switch_page")  --页面切换演示
-- require("win_hzfont")  --内置软件矢量字体演示

7.3 软件烧录

  1. 使用 Luatools 烧录对应型号的最新内核固件
  2. 下载本项目所有脚本文件和图片文件
  3. 将演示图片文件(如 1.jpg2.jpg 等)同.lua脚本文件一起烧录到脚本分区
  4. 设备自动重启后开始运行选定的演示模块

7.4 功能测试

所有组件综合演示(带滚动功能,使用默认字体)

7.5 预期效果

  • 响应式设计:所有组件支持触摸交互
  • 主题支持:支持浅色/深色主题切换
  • 滚动功能:支持横向和纵向滚动页面
  • 动态更新:支持实时数据更新显示
  • 事件处理:完整的触摸和点击事件处理

八、使用合宙 LuatOS-PC 模拟器仿真 exeasyui

8.1 PC 模拟器说明

  • 合宙 LuatOS-PC 模拟器是一个能在 win10/win11 上模拟运行 lua 脚本的仿真软件,内置 LuatOS 内核固件,运行.lua 脚本效果与实际设备类似;
  • 目前 PC 模拟器可以通过 LuaTools 工具的资源管理器进行下载,所以我们需要先下载安装 LuaTools 工具,然后再通过 LuaTools 工具来下载 LuatOS-PC 模拟器,最后通过 LuatOS-PC 模拟器运行 exeasyui 演示 demo;

8.2 LuatOS-PC 模拟器安装步骤

1、点击下载:Luatools v3 下载调试工具

2、通过 LuaTools 工具下载 LuatOS-PC 模拟器

  • LuaTools 工具安装完毕后,点击首页面左上角的--账户--打开资源下载
  • 选择-公共资源--LuatOS 的 PC 模拟器--选择最新版本 LuatOS-PC 模拟器--点击开始下载(非刷机)
  • (这里以Air780EHM为例,实际选择Air8000最新的固件)

8.3 下载底层固件和上层运行脚本

  1. 下载运行所需固件,点击资源管理--选择 Air8000 的 LuatOS 固件--下载最新版本的 1 号固件和 14 号固件
  2. 下载本演示 demo 内所有.lua 脚本文件、images 文件夹内的图片

8.4 使用 LuatOS-PC 模拟器仿真 运行 exeasyui 演示 demo

1、返回 Luatloos 工具首页,点击--项目管理测试

2、创建一个项目并命名

3、选择固件刚才下载的固件--点击打开,路径在 Luatools 目录下 resource\LuatOS_Air8000\LuatOS-SoC_VXXXX_Air8000

4、将下载的 demo 图片资源和.lua文件拖入到项目管理内的脚本和资源列表区域--勾选添加默认 lib--点击模拟器运行--出来的界面就是 demo 在实际设备上运行界面的仿真,可以用鼠标进行交互

5、如需切换 demo 内的演示内容,可打开下载脚本文件中的 mian.lua 文件,将需要演示 demo 的 require 前面--去掉,将不需要演示 demo 的 require 前面加上--。注释掉 require 的其他 demo 文件后,再点击模拟器运行,就会出现所 require 的 demo 对应的界面仿真。

  • 比如:需要演示下拉框组件,将-- require("win_combo_box") 改为 require("win_combo_box") ,并把其他加载的组件改为注释状态。

九、常见问题

1、显示异常

  • 检查 LCD 接线是否存在异常
  • 确认 hw_font_drv.lua 内屏幕型号及其参数配置是否正确

2、触摸无响应

  • 检查 I2C 接线是否存在异常
  • 确认确认 hw_font_drv.lua 内触摸芯片型号配置正确

3、字体显示异常

  • 确认选择的字体驱动与硬件匹配
  • 检查固件版本是否支持所选字体

4、图片无法显示

  • 确认图片文件已正确烧录
  • 检查文件路径和名称是否正确

5、系统运行缓慢

  • 检查是否有过多的组件同时渲染
  • 适当调整刷新间隔时间

6、 调试技巧

  • 使用 log.info() 输出调试信息
  • 检查系统内存使用情况
  • 逐步启用组件排查问题