MAC上使用Slint在ESP32上开发UI界面

MAC上对Slint的支持不是很好原生环境下折腾了很久也没有成功,这里改为使用Docker

准备环境

需要一个预装了 Slint 编译环境和 ESP-IDF 的 Docker 镜像。

拉取镜像

建议使用官方的 ESP-IDF 镜像作为基础:

docker pull espressif/idf:latest

为了能让 Docker 访问你的 ESP32 开发板,但最简单的方法是在 Docker 内编译,在宿主机(Mac)上烧录。

运行容器

docker run -it --rm -v $(pwd):/project -w /project espressif/idf:latest

创建ESP-IDF项目

my-esp32-slint-project/
├── CMakeLists.txt              # 项目顶层 CMake
├── main/
│   ├── CMakeLists.txt          # main 组件 CMake
│   ├── main.cpp                # C++ 业务逻辑与驱动初始化
│   └── idf_component.yml       # 声明依赖项(LCD/触摸驱动)
├── ui/
│   ├── app.slint               # Slint UI 设计文件
│   └── CMakeLists.txt          # UI 编译配置
├── sdkconfig.defaults          # 预设配置(如开启 PSRAM)
└── docker-compose.yml          # 可选:方便一键启动 Docker 环境

ui/app.slint (界面设计)

import { Button, VerticalBox, CheckBox } from "std-widgets.slint";

export component AppWindow inherits Window {
    width: 320px;
    height: 240px;
    background: #1a1a1a;

    callback toggle_led(bool);

    VerticalBox {
        padding: 20px;
        spacing: 15px;
        alignment: center;

        Text {
            text: "ESP32 Slint 控制面板";
            color: white;
            font-size: 18px;
            horizontal-alignment: center;
        }

        CheckBox {
            text: "控制板载 LED";
            toggled => {
                root.toggle_led(self.checked);
            }
        }
    }
}

main/idf_component.yml (驱动依赖)

dependencies:
  idf: ">=5.0"
  slint/slint: "^1.15.1"

main/main.cpp (核心逻辑)

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "app.h" // Slint 自动生成的头文件

#define BLINK_GPIO GPIO_NUM_2

extern "C" void app_main() {
    // 1. 初始化 GPIO
    gpio_reset_pin(BLINK_GPIO);
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);

    // 2. 初始化显示屏 (此处省略复杂的 SPI/LCD 初始化代码,通常调用 esp_lcd 函数)
    // ... 

    // 3. 启动 Slint 实例
    auto ui = AppWindow::create();

    // 4. 绑定回调
    ui->on_toggle_led([](bool active) {
        gpio_set_level(BLINK_GPIO, active ? 1 : 0);
        printf("LED 状态: %s\n", active ? "开启" : "关闭");
    });

    // 5. 进入 Slint 运行循环
    ui->run();
}

CMakeLists.txt (项目顶层)

cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(SlintIdf)

在 main 目录下的 CMakeLists.txt 是项目的核心,它负责将 Slint 的 UI 文件编译成 C++ 代码,并将其与 ESP-IDF 的组件(驱动、GPIO 等)链接在一起。

以下是针对该项目的 main/CMakeLists.txt 完整内容:

idf_component_register(SRCS "main.cpp"
                    INCLUDE_DIRS ".")

# 移除 find_package(Slint),由 IDF 自动处理
slint_target_sources(${COMPONENT_LIB} "../ui/app.slint")

# 链接 Slint 组件。
# 在 IDF 5.x 中,组件库名通常就是文件夹名,即 slint
target_link_libraries(${COMPONENT_LIB} PRIVATE Slint::Slint)

slinttargetsources: 这是一个魔法宏。它会检测 ../ui/app.slint 的变化。如果你修改了 UI 设计,下次执行 idf.py build 时,它会自动重新生成 app.h。

头文件引用: 编译后,你可以在 main.cpp 中直接使用 #include "app.h",这个文件会被生成在 build 目录的深处,但 CMake 会自动处理路径。

编译项目

# 启动 Docker 并挂载当前目录
docker run -it --rm -v $(pwd):/project -w /project espressif/idf:latest /bin/bash

# 进入容器后(在容器内执行):
idf.py set-target esp32
idf.py build

如果修改的cmake清理内容重新编译

# 清除旧的缓存(非常重要)
rm -rf build ManagedComponents

# 重新配置并编译
# 这一步会自动连接网络下载 Slint 及其依赖项
idf.py reconfigure
idf.py build

在 Mac 上烧录

编译成功后,build 文件夹内会生成 flashing_assistant.sh 或者直接使用 esptool.py

# 查找你的串口设备
ls /dev/cu.usbserial-*
# 烧录
esptool.py -p /dev/cu.usbserial-1430-b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/your_project_name.bin

# 也可以通过idf.py烧录
idf.py -p /dev/cu.usbserial-1430 flash monitor

文档信息

版权声明:可自由转载(请注明转载出处)-非商用-非衍生

发表时间:2026年2月27日 14:56