无人机智能硬件【免费下载链接】qgroundcontrolCross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)项目地址https://gitcode.com/gh_mirrors/qg/qgroundcontrol点击查看免费下载QGroundControlQGC是一个跨平台地面站应用支持 Android、iOS、macOS、Linux、Windows其用户界面UI设计遵循一套独特而统一的模式UI 页面全部由 QML 编写并与用 C 编写的自定义 Controller 进行多次通信。这套模式是 MVCModel-View-Controller设计模式的一种经过改良的变体文档原话为 somewhat hacked variant of the MVC design pattern。本文以官方开发者指南《用户界面设计》为核心骨架结合仓库源码src/QmlControls、src/PlanView、src/FactSystem等深入讲解 QML 与 C 的三种绑定机制、Controller 的编写方式、配套控件与调色板体系以及该模式背后的多设备设计取舍。读完本文你将理解 QGC 中任何一张页面的视图层 控制层是如何组织与通信的并能据此上手编写或维护自己的 QGC QML 页面。QGC UI 的核心模式QML 视图 C Controller在 QGC 中一个 UI 页面通常由两部分构成视图层View用 QML 编写的页面负责界面布局、交互与视觉呈现控制层Controller用 C 编写、通过 Qt 元对象系统暴露给 QML 的类负责业务逻辑、数据访问与状态维护。这两部分通过 QML 引擎的上下文属性和类型注册机制相连Controller 以 QML 元素的形式如PlanMasterController、FactPanelController直接实例化在 QML 页面中页面通过属性绑定Property Binding读取其Q_PROPERTY通过信号signal接收状态变化通过Q_INVOKABLE方法触发动作。这与传统 MVC 中View 观察 Model、Controller 更新 Model的严格分层不同——QGC 没有独立的 Model 类Controller 直接暴露数据属性因此文档将其称为改良变体。从源码看这种模式的改良体现在Controller 直接作为 QML 元素存在例如FactPanelController在 src/FactSystem/FactControls/FactPanelController.h 中声明为QML_ELEMENT并暴露Vehicle *vehicle属性以及getParameterFact()、parameterExists()等可调用方法Controller 负责组装子对象并注入 QML例如 src/PlanView/PlanView.qml 中页面通过planMasterController.missionController、planMasterController.geoFenceController、planMasterController.rallyPointController访问由 C 侧创建好的子控制器再通过_missionController.visualItems把任务项模型暴露给地图与列表视图一个 QML 页面可以挂载多个 Controller如 src/PlanView/PlanTreeView.qml 中同一列表视图依据当前编辑层任务/围栏/集结点绑定不同的 Controller。按照官方文档QML 代码正是通过以下三种机制绑定到与系统相关的信息自定义 ControllerC 对象页面专属的业务逻辑与数据全局QGroundControl对象提供对活动 Vehicle、链路管理、设置系统等全局服务的访问FactSystem事实系统提供对参数的访问某些情况下提供自定义 Facts。下文逐一深入。机制一自定义 Controller——QML 与 C 的通信桥梁Controller 是 QGC 中页面级逻辑的载体。以 Plan 视图为例src/PlanView/PlanView.qml 中有这样一段PlanMasterController { id: planMasterController flyView: false Component.onCompleted: { _planMasterController.start() _missionController.setCurrentPlanViewSeqNum(0, true) } ... }PlanMasterController是一个 C 类通过 Qt QML 类型系统注册为 QML 元素。它负责创建并管理任务控制器MissionController、地理围栏控制器GeoFenceController与集结点控制器RallyPointController并通过Q_PROPERTY把这些子对象暴露给 QMLproperty var _missionController: _planMasterController.missionController property var _geoFenceController: _planMasterController.geoFenceController property var _rallyPointController: _planMasterController.rallyPointControllerQML 页面可以直接调用 C 方法并接收返回值例如 PlanView 中保存/上传前的校验function checkReadyForSaveUpload(save) { if (readyForSaveState() VisualMissionItem.NotReadyForSaveData) { waitingOnIncompleteDataMessage(save) return false } else if (readyForSaveState() VisualMissionItem.NotReadyForSaveTerrain) { waitingOnTerrainDataMessage(save) return false } return true }这里的readyForSaveState()就是由 C Controller 提供的Q_INVOKABLE方法VisualMissionItem.NotReadyForSaveData等枚举值也是从 C 侧Q_ENUM注册进 QML 的。FactPanelController面向事实的通用控制器基类另一类典型的 Controller 是FactPanelControllersrc/FactSystem/FactControls/FactPanelController.h。它被声明为QML_ELEMENT是许多参数/设置面板 C 控制器的基类核心能力包括vehicle属性暴露当前关联的Vehicle对象getParameterFact(int componentId, const QString name)按组件 ID 与参数名获取对应的Fact对象parameterExists()判断参数是否存在getMissingParameters()查询首次下载时尚未就绪、但现在应该可用的参数。它配合 QML 侧的信号missingParametersAvailable使用让页面在参数真正可用后再刷新 UI避免参数未就绪竞态。可以看到Controller 承担了把 C 世界的数据安全地搬运到 QML 世界的职责。通信机制小结Q_PROPERTY / Q_INVOKABLE / 信号槽QGC 中 QML 与 C 通信遵循标准 Qt 元对象系统约定机制作用示例Q_PROPERTY暴露只读/可写属性支持 QML 属性绑定与NOTIFY信号联动刷新Fact.value、FactPanelController.vehicleQ_INVOKABLE暴露可从 QML 调用的方法可带参数并返回结果PlanMasterController.readyForSaveState()、Fact.validate()signal /NOTIFYC 侧状态变化时通知 QML 更新绑定Fact.valueChanged、FactPanelController.missingParametersAvailableQ_ENUM/QML_NAMED_ELEMENT把枚举与类注册进 QML 命名空间VisualMissionItem.NotReadyForSaveData、QGroundControl全局对象机制二全局 QGroundControl 对象——系统级服务的门面在 QML 中QGroundControl是一个全局单例对象提供对整个应用系统级服务的访问。其 C 实现为QGroundControlQmlGlobalsrc/QmlControls/QGroundControlQmlGlobal.hclass QGroundControlQmlGlobal : public QObject { Q_OBJECT QML_NAMED_ELEMENT(QGroundControl) QML_SINGLETON ... };QML_NAMED_ELEMENT(QGroundControl)意味着 QML 里直接以QGroundControl作为元素名访问QML_SINGLETON表示它是全局单例无需实例化即可直接引用。该对象暴露的常用属性均为CONSTANT或带NOTIFY包括linkManager链路管理器TCP/UDP/串口等链接multiVehicleManager多飞行器管理器通过它可以访问当前活动 VehiclesettingsManager设置管理器按模块暴露各类appSettings、planViewSettings等corePlugin核心插件实例可被自定义构建替换globalPalette全局 QGC 调色板对象返回始终可用的颜色组unitsConversion单位换算工具qgcVersion/qgcAppDate/qgcDailyBuild版本与构建信息zOrderTopMost/zOrderWidgets/zOrderMapItems等地图分层中不同元素的 Z 序常量flightMapPosition/flightMapZoom飞行地图的中心点与缩放级别可读写、带信号。它还提供一批Q_INVOKABLE方法典型的有saveGlobalSetting(key, value)/loadGlobalSetting(key, defaultValue)读写全局设置showMessageDialog(owner, title, text, buttons, acceptFunction, closeFunction)显示消息对话框支持回调函数startPX4MockLink(...)、startAPMArduCopterMockLink(...)等启动各类模拟链路Mock Link用于开发与测试copyToClipboard(text)复制文本到系统剪贴板。在真实页面中它的用法非常普遍。例如 src/PlanView/PlanView.qmlproperty var _appSettings: QGroundControl.settingsManager.appSettings property var _planViewSettings: QGroundControl.settingsManager.planViewSettings ... onVisibleChanged: { if(visible) { editorMap.zoomLevel QGroundControl.flightMapZoom editorMap.center QGroundControl.flightMapPosition } }以及通过QGroundControl.showMessageDialog(_root, qsTr(Unable to %1)...)弹出模态提示见 src/PlanView/PlanView.qml。调色板的使用也通过全局对象QGroundControl.globalPalette.buttonHighlight、QGroundControl.globalPalette.buttonText见 src/QmlControls/AltFrameDialog.qml。从源码结构可以推断QGroundControl相当于门面Facade——把LinkManager、MultiVehicleManager、SettingsManager、VideoManager、ADSBVehicleManager、NTRIPManager等一堆子系统统一收口到单个 QML 可见对象上避免每个页面各自创建或到处传递单例。应用层单例QGCApplication 与 qgcApp()与 QML 侧的QGroundControl相对应C 侧还有一个全局应用对象QGCApplication。它在 src/QGCApplication.h 中被定义为#define qApp (static_castQGCApplication*(QGuiApplication::instance())) #define qgcApp() qAppQGCApplication继承自QGuiApplication提供reportMissingParameter()、showAppMessage()、msecsSinceBoot()、qmlAppEngine()等应用级能力。C 代码中凡需访问应用级状态例如 src/FactSystem/Fact.cc 中if (qgcApp())的判空用法都会经由qgcApp()获取。机制三FactSystem——参数与自定义事实的数据层文档明确指出 QML 绑定信息的第三个来源是FactSystem它提供对参数的访问在某些情况下提供自定义 Facts。这一体系的完整介绍见 docs/zh/qgc-dev-guide/fact_system.md其核心概念如下。Fact系统中的单个值Fact是系统中单个值的封装src/FactSystem/Fact.h。它被声明为QML_ELEMENT意味着可以直接在 QML 中使用。每个 Fact 暴露大量Q_PROPERTY值相关value可读写带NOTIFY valueChanged、rawValue、valueString、enumOrValueString、valueEqualsDefault元数据相关name、label、units、shortDescription、longDescription、category、group取值范围min、max、userMin、userMax、increment、decimalPlaces枚举相关enumStrings、enumValues、enumIndex行为标记readOnly、writeOnly、volatileValue、vehicleRebootRequired、qgcRebootRequired。同时提供validate(cookedValue, convertOnly)、clamp(cookedValue)、rawToCooked(rawValue)等Q_INVOKABLE方法用于在 UI 层做输入校验、限幅与单位换算。这正是Fact 驱动自动 UI 生成的基础——控件只需绑定 Fact取值范围、单位、枚举选项、输入校验都由 Fact 与 FactMetaData 自动给出。FactMetaData驱动自动 UI 的元数据与每个 Fact 关联的FactMetaData提供关于 Fact 的详细信息类型、范围、单位、枚举、默认值、描述等用于驱动用户界面自动生成和验证。元数据既可以由代码构造也可以由 JSON 文件提供如src/Settings、src/MissionManager目录下大量*.FactMetaData.json/*.SettingsGroup.json文件。FactGroup 与 Fact ControlsFactGroup一组 Fact 的集合用于组织事实并管理用户自定义事实。飞行器相关事实含固件插件factGroups函数返回的组内事实可通过getFact(factName)或getFact(factGroupName.factName)获取Fact Controls事实控件QML UI 控件连接到 Fact 及其 FactMetaData为用户提供修改/显示 Fact 值的界面例如FactSlider、FactTextField、FactComboBox等见 src/FactSystem/FactControls 目录。自定义构建支持用户定义的事实可以通过覆盖FirmwarePlugin的factGroups函数添加到自定义固件插件类中返回 FactGroup 名称映射通过扩展FactGroup类并以其构造函数传入包含必要信息的 JSON 文件来定义事实元数据还可以通过覆盖FirmwarePlugin的adata原文如此应为 metadata 相关函数更改现有事实的元数据。这一机制让自定义构建custom build能够在不改动 QML 的前提下扩充 UI 可展示的参数。为什么 QGC 的 QML 无法使用 Qt QML Designer官方文档特别提醒由于 QGC 使用的 QML 的复杂性以及它依赖与 C 对象通信来驱动 UI无法使用 Qt 提供的 QML Designer 来编辑 QML。这与前述三种绑定机制直接相关大量属性来自 C 单例与 Controller如QGroundControl.globalPalette.buttonHighlight、controller.visualItems在设计器中这些对象要么不存在、要么处于未初始化状态页面启动即依赖 C 侧完成的初始化如PlanMasterController.start()脱离运行环境的静态编辑无法正确呈现动态重排多设备自适应布局依赖运行时屏幕尺寸与ScreenTools设计器的固定画布无法模拟。因此 QGC 开发者实际都是直接手写 QML 源码配合 QGC 自身的单元测试与 QML UI 测试见 test/QmlUITests 目录来验证界面行为。支撑这套模式的配套体系围绕上述QML Controller核心模式QGC 还提供了一套统一的配套体系让所有页面共享一致的外观与交互。可复用控件集QGroundControl.ControlsQGC 提供一组基础控件用于构建界面详见 docs/zh/qgc-dev-guide/user_interface_design/controls.md。它们一般是 Qt 原生 QML 控件之上的薄封装用 QGC 调色板绘制。使用时导入import QGroundControl.Controls标准 Qt QML 控件的 QGC 变体功能与对应 Qt 控件相同仅绘制上使用 QGC 调色板QGCButtonQGCCheckBoxQGCColoredImageQGCComboBoxQGCFlickableQGCLabelQGCMovableItemQGCRadioButtonQGCSliderQGCTextFieldQGC 独有控件用于创建标准 UI 元素DropButton——圆形按钮点击后展开一组选项面板典型例子是 Plan 视图中的同步Sync按钮ExclusiveGroupItem——支持 QMLExclusiveGroup概念的自定义控件的基项QGCView——系统中所有顶级视图的基本控件提供对 FactPanel 的支持并负责显示QGCViewDialog与QGCViewMessageQGCViewDialog——从 QGCView 右侧弹出的对话框可指定接受/拒绝按钮及对话框内容典型例子是点击某个参数后弹出的值编辑器对话框QGCViewMessage——QGCViewDialog的简化版本允许指定按钮与简单文本消息QGCViewPanel——QGCView内部的主要视图内容RoundButton——以图片作为内部内容的圆形按钮控件SetupPage——所有安装载具组件页面Setup 视图的基本控件提供标题、说明与组件页面内容区SelectableControl——允许用户从一组控件中选择要显示的内容桌面端右键、移动端长按显示选择 UI典型用法是让用户在多种仪表显示变体之间切换。这些控件的实现集中在 src/QmlControls 目录如QGCButton.qml、QGCCheckBox.qml、DropButton.qml、ExclusiveGroupItem.qml、SetupPage.qml、SelectableControl.qml等它们共同构成一次编写、处处复用的 UI 积木。字体与调色板Font and PaletteQGC 拥有一套标准字体与调色板所有用户界面都应遵守详见 docs/zh/qgc-dev-guide/user_interface_design/font_palette.mdQGCPaletteQGC 调色板提供浅色light与深色dark两种变体。浅色适合户外使用深色适合室内。正常情况下绝不应直接为 UI 指定颜色而应始终使用调色板中的颜色否则你创建的界面将无法随浅色/深色样式切换。QML 中通过QGroundControl.globalPalette获取全局调色板如 src/QmlControls/AltFrameDialog.qml 中的buttonHighlight、buttonText或实例化QGCPalette { id: qgcPal; colorGroupEnabled: true }按控件局部使用如 src/QmlControls/AppSettings.qmlQGCMapPaletteQGC 地图调色板用于绘制在地图之上的颜色。由于地图样式不同尤其是卫星图与街道图需要不同的颜色才能清晰绘制卫星图需要更浅的颜色街道图需要更深的颜色。QGCMapPalette为此提供一组颜色并支持在地图上切换浅色/深色ScreenTools屏幕工具提供可用于指定字体大小的值同时提供屏幕尺寸信息以及 QGC 是否运行在移动设备上的信息。典型用法如 src/PlanView/PlanView.qml 中ScreenTools.defaultFontPixelHeight、ScreenTools.defaultFontPixelWidth参与计算边距与面板宽度。多设备设计模式一个代码库适配所有屏幕QGC 设计用于从桌面、笔记本、平板到小型手机屏幕等多种设备详见 docs/zh/qgc-dev-guide/user_interface_design/multi_device_pattern.md。其核心思路是用单一 QML 代码库 布局重排适配不同外形而不是为每种屏幕尺寸单独编码。该模式建立在三个支柱之上Qt 布局控件LayoutQGC 没有针对不同屏幕尺寸的分离 UI 代码通常依靠 QML 的 Layout 能力重排同一组 UI 代码某些情况下在小屏幕上隐藏次要细节简单的可见性切换模式FactSystem系统内部统一管理所有单个数据这个数据模型连接到控件控件自动获得数据驱动的 UI严重依赖可重用控件QGC UI 由可复用控件与 UI 元素构建任何添加到可复用控件的新功能立即可用于整个 UI这些可复用控件连接 FactSystem 的 Facts自动提供合适的 UI。设计取舍的背景QGC 以约 1 人开发团队的高效维护为前提严格遵循该模式否则会导致开发变慢、质量下降。这一决策使 QGC 能凭单一代码库发布到多个操作系统与多种外形设备。其优先级顺序是平板 笔记本 桌面 手机任何小屏幕。手机大小的屏幕当前优先级最低Fly 视图等主动飞行显示投入更多精力而 Setup、Plan 等视图在小屏幕上功能可用但体验可能较差。该模式也有明确代价原文列出的缺点UI 最终是桌面/笔记本/平板/手机的混合风格未必对其中任何一种做到优化感离优先级目标越远混合方法的体验越差小屏手机在可用性上受影响最大某些场景下可复用控件集未必提供绝对最佳 UI但为了不新增维护面仍坚持复用所有操作系统使用同一套 UI 代码QGC 不遵循各操作系统自身的 UI 设计准则有自己的混合视觉风格例如 Android 上的 QGC 不一定像安卓应用iPhone 上的 QGC 也不会像大多数 iPhone 应用那样工作——但该风格对各类系统用户都是可理解的。优点原文所列由于使用混合模型与控件集一次完成 UI 编码设计新功能耗时更短布局重排在 Qt QML 中非常强大UI 功能代码跨外形一致因此可仅在一个平台上做功能测试布局流通过移动模拟器做视觉检查即可常见做法桌面构建调整窗口大小测试重排通常也覆盖平板尺寸手机小屏用模拟器直观验证。结语一条贯穿 QGC 开发的主线从 docs/zh/qgc-dev-guide/user_interface_design/index.md 出发可以看到QGC 用户界面开发的主线非常清晰QML 只负责怎么呈现C Controller 负责数据与逻辑二者通过属性绑定、Q_INVOKABLE方法与信号槽通信QGroundControl全局单例收口所有系统级服务FactSystem 提供统一的数据模型与自动 UI 能力可复用控件、调色板与多设备布局规则保证所有页面风格一致、一套代码跑遍所有平台。无论你要为 QGC 新增一个设置页、任务项还是自定义构建的专属界面遵循QML 视图 Controller 全局对象 FactSystem这条模式主线再配合控件集与调色板约定就能写出与官方页面一致、可维护、可跨设备的 UI 代码。赞分享无人机智能硬件【免费下载链接】qgroundcontrolCross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)项目地址https://gitcode.com/gh_mirrors/qg/qgroundcontrol点击查看免费下载相关推荐QGroundControl 用户界面设计模式QML 页面与 C Controller 的 MVC 变体架构QGroundControl 用户界面设计模式QML 页面与 C Controller 的 MVC 变体架构 QGroundControlQGC的界面无人机智能硬件QGroundControl UI 设计架构解析QML 页面与 C Controller 的 MVC 变体及多设备适配实践QGroundControl UI 设计架构解析QML 页面与 C Controller 的 MVC 变体及多设备适配实践 QGroundControl无人机智能硬件QGroundControl 用户界面设计指南QML C Controller 架构、控件体系与多设备适配模式QGroundControl 用户界面设计指南QML C Controller 架构、控件体系与多设备适配模式 QGroundControlQGC无人机智能硬件上一篇3分钟搞定Deepin Boot Maker零门槛U盘启动盘制作神器下一篇Milkdown 插件系列milkdown/plugin-diff 差异审阅插件深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考