# Qt Embedded 说明 ## 1. QPA QPA 的全称是 Qt Platform Abstraction,即 Qt 平台抽象层。在 Qt5 中替代 QWS(Qt Window System)。QPA 插件是通过对各种 QPlatform* 类进行子类化来实现的。有几个根类,例如用于窗口系统集成的 QPlatformIntegration 和 QPlatformWindow,以及用于更深入的平台主题和集成的 QPlatformTheme。QStyle 不是 QPA 的一部分。QPA 类没有源代码或二进制兼容性保证,这意味着平台插件只能保证与它开发的Qt版本一起使用。 在 Qt4 在编译时需要引入平台相关代码,其可移植性差,Qt5 通过引入 QPA 来剥离平台相关代码,提高跨平台特性。 ### 1.1. Qt 应用程序的 QPA 参数/环境变量 优先使用环境变量中的宏定义,如 QT_QPA_PLATFORM,其次使用程序运行时指定的参数。 指定 mouse、touch、keyboard(需要加载 hid、hid-generic、usbhid 驱动): ```bash # 使用 linuxfb -platform linuxfb:fb=/dev/fb0:mmsize=1024x600 -plugin evdevmouse:/dev/input/event -plugin evdevtouch:/dev/input/event -plugin evdevkeyboard:/dev/input/event # 使用 directfb -platform directfb ``` 使用 directfb 不需要指定 fbdev、input 等,这些信息在 /etc/directfbrc 中指定,具体查看 directfbrc 的 man 手册。 #### 1.1.1 常用环境变量 ```bash # 指定插件安装路径.qp export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/qt/plugins # 指定 Platform 参数. export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0 # 设置字体目录. export QT_QPA_FONTDIR=/usr/share/fonts # 打开插件调试. export QT_DEBUG_PLUGINS=1 ``` #### 1.1.2. -platform 参数(QPA Platform) 主要见 plugin/platforms 文件夹下有哪些插件,如: - linuxfb - directfb - weston #### 1.1.3. -plugin 参数(QPA Evdev Plugin) 主要见 plugin/generic 文件夹下的 libqevdev* 插件,如: - evdevkeyboard - evdevmouse - evdevtablet - evdevtouch ## 1.2. EGLFS ```bash export QT_QPA_EGLFS_KMS_CONFIG=kms_config.json export QT_QPA_PLATFORM=eglfs export QT_QPA_EGLFS_INTEGRATION=eglfs_kms export QT_LOGGING_RULES=qt.qpa.*=true export QT_QPA_EGLFS_DEBUG=1 ``` sudo cat /sys/kernel/debug/dri/0/summary kms_config.json 如下: ```json { "device": "/dev/dri/card0", "hwcursor": false, "pbuffers": true, "outputs": [ { "name": "HDMI1", "mode": "1920x1080" } ] } ``` QT_QPA_EGLFS_INTEGRATION: - eglfs_x11 - eglfs_kms - eglfs_emu - eglfs_kms_egldevice ## 2. 自启动 ### 2.1. init 方式启动 如果程序能通过命令行进行启动,则可以通过系统服务来实现自开机自启动。 首先,在 /etc/init.d/ 文件夹下创建一个启动脚本,比如 mydemo: ```bash #!/bin/bash ### BEGIN INIT INFO # Provides: airobot # Required-Start: $all # Required-Stop: # Default-Start: 2 5 # Default-Stop: # Short-Description: your description here ### END INIT INFO start(){ /path/to/demo -platform linuxfb:fb=/dev/fb0:mmsize=1920x1080 & } stop(){ killall -q demo } restart(){ stop start } case $1 in "start") start ;; "stop") stop ;; "restart") restart ;; *) start esac ``` 注意文件头 Default-Start 等注释是必须的,用于指定 runlevel。在 init 脚本中,start、stop 和 restart 是几个必须支持的命令,根据实际需求,设置运行环境,编写对应命令即可。 之后通过 chkconfig 或 update-rc.d(Ubuntu 系统) 对服务进行配置即可: update-rc.d 使用方式如下: ```bash # 添加服务 sudo update-rc.d [service name] defaults # 使能 # 出现“Failed to enable unit: Unit /run/systemd/generator.late/mydemo.service is transient or generated.” # 说明 default 执行时已经生成了对应的 .service 文件,可以忽略该错误。 sudo update-rc.d [service name] enable # 移除 sudo update-rc.d -f [service name] remove # 查看当前服务 ls /etc/init.d/ ``` chkconfig 使用方式如下: ```bash # 添加 chkconfig --add mydemo # 删除 chkconfig --del mydemo # 设置 runlevel chkconfig --level 2345 mydemo on # 查看服务 chkconfig --list | grep mydemo ``` ### 2.1. systemd 方式启动 在 /usr/lib/systemd/system 下创建 mydemo.service 文件,参考内容如下: ```service [Unit] Description=MyDemo # After=syslog.target # After=network.target # After=multi-user.target # After=graphical.target After=plymouth-quit-wait.service # After=systemd-logind.service [Service] RestartSec=2s Type=simple User=root Group=root WorkingDirectory=/path/to/workDirectory ExecStart=/path/to/demo/demo -platform linuxfb:fb=/dev/fb0:mmsize=1920x1080 Restart=always [Install] WantedBy=multi-user.target ``` 也可以使用 After=graphical.target。 然后使用 systemctl 命令控制服务: ```bash sudo systemctl enable mydemo sudo systemctl start mydemo sudo systemctl stop mydemo sudo systemctl disable mydemo ``` 如果 Screen 的虚拟终端遮蔽了 QPA 应用程序,则可以将其关闭: ```bash sudo systemctl mask getty@tty1.service ``` ## 3. 外部参考资料 1. [Qt for Embedded Linux](https://doc.qt.io/qt-6/embedded-linux.html)