3. Qt核心概念回顾
从 LVGL 迁移到 Qt,最大的认知转变不是“换一套 API”,而是从“手动绘制 + 定时器轮询”转向“对象树 + 事件驱动 + 声明式描述”。LVGL 中我们习惯自己管理 lv_obj_t 的父子关系、手动调用 lv_timer_handler()、用 lv_obj_set_style_* 逐项设置样式;而 Qt 把这些职责拆分为若干清晰的核心机制。理解这些机制之间的分工,是后续迁移工作的地基。
一、QWidget 与 QML:两种界面构建范式
Qt 提供两套并行的 UI 技术栈。QWidget 是传统的命令式 C++ 方案,控件是真实对象,通过继承和成员函数配置;QML 是声明式方案,用类似 JSON 的语法描述界面,底层由 Qt Quick 场景图渲染,天然适合动画与触摸交互。
- QWidget:成熟稳定,控件丰富,适合桌面工具、工业上位机;样式依赖 QStyle 与样式表,动画能力弱。
- QML:声明式、属性绑定、内置动画与状态机,适合嵌入式触摸屏、仪表盘;逻辑可用 C++ 后端暴露给 QML。
迁移时若原 LVGL 界面以静态控件为主,QWidget 迁移成本更低;若大量使用动画、滑动、渐变,QML 更贴近 LVGL 的视觉表现力。两者可以混合:用 QQuickWidget 把 QML 嵌入 QWidget 窗口。
二、信号槽:对象间的解耦通信
LVGL 用回调函数 lv_obj_add_event_cb() 绑定事件,回调与对象强耦合。Qt 的信号槽机制把“谁发出”和“谁接收”彻底分离:发送方只负责 emit,接收方通过 connect 注册,双方无需知道彼此类型。
// 传统写法:编译期检查
connect(btn, &QPushButton::clicked, this, &MainWindow::onBtnClicked);
// 新式 lambda:可捕获上下文
connect(slider, &QSlider::valueChanged, this, [=](int v){
label->setText(QString::number(v));
});
// 跨线程:自动排队
connect(worker, &Worker::finished, this, &MainWindow::handleDone,
Qt::QueuedConnection);
关键点:信号槽默认自动连接,跨线程时自动转为队列连接;连接类型可显式指定 Qt::DirectConnection、QueuedConnection、BlockingQueuedConnection。迁移中,LVGL 的 LV_EVENT_VALUE_CHANGED 通常对应 valueChanged 信号,LV_EVENT_CLICKED 对应 clicked。
三、事件系统:从底层输入到高层信号
Qt 的事件系统是信号槽的上游。鼠标、键盘、触摸、定时器、绘制请求都先以 QEvent 子类形式派发给目标对象,经过 event() 分发到 mousePressEvent()、keyPressEvent()、paintEvent() 等虚函数。若事件未被处理,可调用 ignore() 向上冒泡给父对象。
与 LVGL 的差异在于:LVGL 的事件回调直接挂在对象上,而 Qt 的事件有“过滤器”机制——installEventFilter() 可让一个对象监视另一个对象的事件,这在做全局快捷键、拖拽拦截时非常有用。
lv_indev 输入设备在 Qt 中由平台插件自动处理,通常无需手动读取触摸坐标;若需自定义手势,重写 event() 或安装事件过滤器即可。四、样式表、布局管理器与图形视图框架
这三者分别解决“外观”“排布”“复杂图形”三个问题。样式表(QSS)语法接近 CSS,可统一设置颜色、边框、圆角、背景图;布局管理器(QHBoxLayout、QVBoxLayout、QGridLayout、QFormLayout)自动计算控件位置与尺寸,替代 LVGL 中手动 lv_obj_align() 的繁琐;图形视图框架(QGraphicsView / QGraphicsScene / QGraphicsItem)用于管理大量图元、支持缩放、旋转、碰撞检测,适合流程图、组态图、地图类界面。
| LVGL 概念 | Qt 对应机制 | 迁移要点 |
|---|---|---|
| lv_obj_t 对象树 | QObject 父子树 / QWidget 父子 | 父对象析构自动释放子对象 |
| lv_obj_add_event_cb | 信号槽 connect | 解耦,支持 lambda 与跨线程 |
| lv_timer_handler | QEventLoop / QTimer | 由事件循环自动驱动 |
| lv_obj_set_style_* | QSS / QPalette | 样式表可集中管理 |
| lv_obj_align / lv_layout | QLayout 布局管理器 | 自动适配窗口缩放 |
| lv_canvas / 手绘 | QGraphicsView 框架 | 图元化,支持交互与变换 |
下面这张图把 Qt 六大核心机制的组织关系与数据流向串联起来,帮助建立整体心智模型。
五、迁移中的常见误区与复盘
update() 反而造成闪烁,应通过属性变化触发信号。复盘建议:迁移前先画一张“LVGL 对象 → Qt 对象”的映射表,明确每个控件由谁创建、由谁销毁、通过哪个信号通信。把事件回调改造成信号槽时,优先使用新式 connect 语法以获得编译期检查。对于复杂自绘界面,评估是否值得引入 QGraphicsView,而不是继续在 paintEvent() 中手写全部绘制逻辑。掌握这六大机制后,后续的控件映射、样式迁移与性能调优才有稳定的参照系。