# sample_qt 使用说明

## 功能概述

`sample_qt` 是一个基于 Qt + DRM eglfs 的 UI 示例程序，用于演示在芯片上通过 Qt 构建图形界面、完成图形渲染并响应输入事件的完整流程。

- 验证显示路径：Qt 通过 eglfs/DRM 直接渲染到屏幕，验证 DRM 显示链路是否正常工作。
- 验证输入路径：通过触摸屏、鼠标或键盘等输入设备与界面交互，验证输入事件是否能被 Qt 程序正确接收和处理。
- 参考实现：为后续在本平台上开发 Qt 图形应用提供基础工程模板和代码参考。

### 软件架构说明

`sample_qt` 的整体软件架构如下图所示：

![software_architecture_diagram](./_static/_images/sample_qt/software_architecture_diagram.png)

从上到下主要包含以下几个层次：

- `main.cpp` 源码层：包含 `qt_main`、“初始化 Qt 应用”、“创建界面”、“进入事件循环”等步骤，通过这些函数依次完成 Qt 应用初始化、界面创建并最终进入事件循环。
- Qt 框架层：由 `QGuiApplication/QApplication` 对象、界面窗口和控件、Qt 输入事件分发、Qt 渲染处理等模块组成，负责管理应用生命周期、展示界面以及处理来自用户的输入事件。
- Qt 平台插件层：包含 `eglfs` 平台插件和 `evdev` 输入插件，前者将 Qt 的渲染结果输出到 DRM/KMS 提供的显示设备上，后者从输入设备中读取事件并交给 Qt 框架进行分发。
- 显示与输入硬件层：底部为 DRM/KMS 子系统（`/dev/dri`）及其下方的底层显示驱动、面板和桥接芯片驱动（如 `panel-wh-cm480` 等），以及触摸屏、鼠标、键盘等输入设备（`/dev/input/event*`），共同完成最终的图像显示和输入采集。

### 代码位置及目录结构

- 代码位置：`app/samples/platform_samples/sample_qt`
- 目录结构：

```bash
sample_qt/
├── README.md
├── eglfs_kms_config.json
├── main.cpp
├── run.sh
└── Makefile.bak
```

- `main.cpp`：Qt 应用程序入口及主要逻辑代码。
- `eglfs_kms_config.json`：eglfs KMS 相关配置文件，用于指定输出设备、分辨率等参数（具体内容以实际文件为准）。
- `run.sh`：在开发环境中运行示例程序的辅助脚本。
- `README.md`：源码目录下的简要说明文档。
- `Makefile.bak`：备份的 Makefile 文件，实际编译时需要更名为 `Makefile` 文件。

### API 流程说明

![image-20250110-165856.png](./_static/_images/sample_qt/image-20250110-165856.png)

本示例的典型调用流程如下：

1. Qt 应用初始化：
   - 在 `main.cpp` 中创建 `QGuiApplication` 或 `QApplication` 对象，完成 Qt 运行环境的基础初始化（包括平台插件、字体、翻译等）。
2. 界面创建和渲染：
   - 创建主窗口或场景，添加基本控件或绘制元素，用于展示 Qt 渲染效果和输入响应。
   - 设置窗口为全屏显示，适配当前 DRM 输出的分辨率。
3. 平台与显示适配：
   - 通过 Qt 的 `eglfs` 平台插件，将渲染目标绑定到 DRM framebuffer，并根据 `eglfs_kms_config.json` 的配置选择输出设备和模式。
4. 事件循环与输入处理：
   - 进入 Qt 主事件循环，持续从 `/dev/input/event*` 等设备读取输入事件（通过 Qt 输入插件完成），并分发给对应的窗口和控件。
5. 资源释放与退出：
   - 用户退出程序或系统发出退出信号时，Qt 应用退出事件循环，释放窗口和相关资源，最终正常结束进程。

如需进一步了解代码中具体函数调用关系，可以结合 `main.cpp` 源码和 Qt 官方文档阅读。

## 编译部署

### 编译

`sample_qt` 作为 BSP 工程的一部分进行编译，推荐通过 BSP 提供的编译框架完成构建：

- 整体编译 BSP（包括所有示例）：

```bash
./bd.sh
```

- 仅编译 `app/samples/platform_samples` 下的示例（包含 `sample_qt`）：

```bash
./bd.sh app samples/platform_samples
```

- 详细程序编译方式请查阅 [ 编译方法 ](overview.html#span-id-sample-build) 章节。

> ⚠️ **重要提醒：如需运行 sample_qt 示例，必须使用带有 QT5 支持包的根文件系统！**
>
> 当前 BSP 默认提供的 rootfs 镜像（system rootfs）**不含 QT5 相关库和依赖**，直接刷写后 *无法运行任何 Qt 程序*。请务必参考 “[制作 QT支持包](../linux_development/system_component_development/Root_filesystem.html#qt)” 一节，编译并刷写包含 QT5 支持的专用 rootfs 镜像，否则 Qt 示例将无法使用。
> 
> 此外，`sample_qt` 源码目录中默认仅提供 `Makefile.bak` 文件，实际编译示例前请先重命名为 `Makefile`。

### 程序部署

完成 BSP 编译并刷写系统软件镜像后，本示例的可执行文件会被安装到开发板的 `/app/platform_samples/sample_qt` 目录下：

- 可执行程序：`/app/platform_samples/sample_qt/sample_qt`

如果在开发环境中手工编译生成了可执行文件，也可以将整个 `sample_qt` 目录（包括必要的配置和资源文件）拷贝到开发板的 `/userdata` 等目录下，赋予执行权限后手动运行：

```bash
chmod +x sample_qt
./sample_qt
```

## 运行

### 程序运行方法

在运行本示例之前，需要先完成 DRM/eglfs 显示环境的准备工作。

1. 确认 DRM 设备节点：
   - 使用命令检查是否存在 `/dev/dri` 相关设备节点：

   ```bash
   ls /dev/dri
   ```

   - 如果不存在 `/dev/dri` 设备节点，需要先加载相关内核模块：

   ```bash
   modprobe drm_kms_helper
   modprobe vs_x5_syscon_bridge
   modprobe vs_drm
   modprobe panel-wh-cm480
   modprobe panel-jc-050hd134
   modprobe sii902x
   modprobe lontium-lt8618
   ```

2. 配置 Qt 平台插件（如有需要）：
   - 本示例使用 `drm eglfs` 显示栈，如果系统中未默认启用 `eglfs`，可以在运行前设置环境变量：

   ```bash
   export QT_QPA_PLATFORM=eglfs
   ```

3. 确认输入设备：
   - 检查触摸屏、鼠标、键盘等输入设备是否在系统中可见：

   ```bash
   ls /dev/input/event*
   ```

4. 在板端运行程序：

   - 从安装目录直接运行：

   ```bash
   cd /app/platform_samples/sample_qt
   ./sample_qt
   ```

   - 也可以使用 `run.sh` 脚本运行：

   ```bash
   ./run.sh
   ```

### 程序参数选项说明

无

### 运行效果

成功运行 `sample_qt` 后，开发板连接的屏幕上会显示一个基于 Qt 的简单菜单界面：

- 界面左上角会显示提示文字：`选择操作：`
- 提示文字下方纵向排列 4 个按钮，每个按钮占一整行，按钮上的文字依次为：
  - `按钮 1：提示`
  - `按钮 2：问候`
  - `按钮 3：关于`
  - `按钮 4：关闭`
- 按钮采用条状布局，整体背景为深色，按钮区域为略浅的条带，并配以浅色文字，便于在屏幕上清晰辨认。

在触摸屏上点击不同按钮（或使用鼠标/触摸屏并确认）时：

- 当前被点击的按钮会有明显的高亮或状态变化，表示已经被选中。
- 程序根据按钮功能执行对应逻辑，例如：
  - 点击“按钮 1：提示”显示提示信息。
  - 点击“按钮 2：问候”显示问候信息。
  - 点击“按钮 3：关于”显示关于信息。
  - 点击“按钮 4：关闭”则退出示例程序并关闭界面。

在串口终端上，可以看到类似下面的日志输出，表明 Qt 应用已正常启动并进入事件循环：

```bash
root@buildroot:/app/platform_samples/sample_qt# ./run.sh
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
```

如果屏幕能够正常显示上述菜单界面，并且点击各按钮时界面有明显响应、程序行为与按钮含义一致且日志无异常报错，即表明 `sample_qt` 示例运行正常。

## 常见问题

### 启动时报错找不到 DRM 设备或 Qt 平台插件

- **问题描述：**
  - 执行 `./sample_qt` 后提示无法打开 DRM 设备，或提示找不到 `eglfs` 平台（如 “Could not find the Qt platform plugin \"eglfs\"” 等）。
- **可能原因：**
  - 内核未加载相关 DRM/显示驱动，导致 `/dev/dri` 设备节点不存在。
  - Qt 运行环境未正确配置 `eglfs` 平台插件。
- **解决方法：**
  - 按“程序运行方法”章节中的步骤，检查并加载以下内核模块：

    ```bash
    modprobe drm_kms_helper
    modprobe vs_x5_syscon_bridge
    modprobe vs_drm
    modprobe panel-wh-cm480
    modprobe panel-jc-050hd134
    modprobe sii902x
    modprobe lontium-lt8618
    ```

  - 如有必要，设置 Qt 平台环境变量：

    ```bash
    export QT_QPA_PLATFORM=eglfs
    ```

