Qt IVI 生成器气候示例
本示例展示了如何使用Qt IVI生成器。
简介
本示例向您展示如何使用Qt IVI生成器构建新组件。基于单个QFace IDL文件,本示例生成了
- 一个包含前端代码的共享库
- 一个后端模拟插件
- 一个演示应用,它显示当前模块中的值
IDL文件
本示例中使用的IDL文件表示一个简化的气候控制接口,它包含一个接口和一些枚举类型。
让我们看看相同的QFace IDL文件的最小版本
module Example.IVI.Climate 1.0; interface ClimateControl { bool airConditioning; int fanSpeedLevel; RecirculationMode recirculationMode; AirflowDirection airflowDirections; } enum RecirculationMode { RecirculationOff = 0x0, RecirculationOn = 0x1, AutoRecirculation = 0x2 } flag AirflowDirection { Windshield = 1, Dashboard = 2, Floor = 4 }
演练
首先,我们需要定义我们想要描述的哪个module
。该module
作为命名空间,因为IDL文件可以包含多个接口。
module Example.IVI.Climate 1.0;
module
最重要的部分是它的interface
定义。
interface ClimateControl {
bool airConditioning;
int fanSpeedLevel;
RecirculationMode recirculationMode;
AirflowDirection airflowDirections;
}
在这种情况下,我们定义了一个名为ClimateControl的interface
,它包含了一些它应提供的属性。每个属性定义必须包含至少一个类型和一个名称。大多数基本类型是内置的,可以在QFace IDL语法中找到。最后两个属性是特殊的,因为它们使用自定义类型,这些类型是在interface
定义之后定义的。
enum RecirculationMode { RecirculationOff = 0x0, RecirculationOn = 0x1, AutoRecirculation = 0x2 } flag AirflowDirection { Windshield = 1, Dashboard = 2, Floor = 4 }
第一个定义是一个包含所有支持值的enum
,包括每个单独项目的数值。第二个定义类似,但使用flag
类型。
注释和注解
与上一节中看到的简洁IDL相比,完整的IDL文件包含了大量的注释和注解。
以/**
开头的注释定义文档语句,并且可以通过生成模板转换为文档标记,例如QDoc或Doxygen。
注解
注解用于向IDL语句添加附加信息。它们是YAML片段,提供键值存储。生成模板定义了支持的注解。
以下是本示例中使用的所有注解的概述以及它们的功能
注解 | 描述 |
---|---|
@config: {zoned: true}
| 指定接口支持不同的区域。 |
@config: {qml_type: "UiClimateControl"}
| 指定从QML使用的组件名称。 |
@config: {id: "example.qtivi.ClimateControl/1.0"}
| 指定用于匹配后端插件的ID。 |
@config_simulator: { range:[0, 50] } | 指定数值属性的合理值范围。 注意:此处使用的 |
@config_simulator: { minimum: 0; maximum: 50 } | 指定数值属性的最低值和最高值。 |
@config_simulator: { domain: ["cold", "mild", "warm" ] } | 指定属性的合理值列表。 |
@config: {interfaceBuilder: "echoInterfaceBuilder"}
| 指定插件应使用自定义函数生成后端实例。 |
除了IDL文件外,还会使用具有相同基本名称的YAML文件来添加额外的配置。这些配置也可以直接添加到IDL文件中,但为了可读性,我们选择将其保持分开。
以下是一些额外配置的示例。
Example.IVI.Climate.ClimateControl: config_simulator: zones: { left : FrontLeft, right : FrontRight, rear: Rear } | 定义了受支持区域的名。 |
Example.IVI.Climate.ClimateControl#recirculationMode: config_simulator: default: RecirculationMode.RecirculationOff | 指定了模拟器后端插件中属性分配的默认值。 |
前端库
现在我们想使用IVI生成器来生成包含我们模块及其接口的C++实现的共享库。
在这种情况下,我们使用frontend
模板,该模板生成一个从QIviAbstractZonedFeature
派生的类,包括所有指定的属性。生成的库使用来自动态后端系统的QtIviCore,提供了一种轻松更改行为实现的方法。更多详细信息,请参阅后端模拟插件。
要调用用于我们的共享库的自动生成器,qmake项目文件需要使用ivigenerator
qmake功能。下面的片段显示了如何这样做
CONFIG += ivigenerator QFACE_SOURCES = ../example-ivi-climate.qface
通过将ivigenerator
添加到CONFIG
变量中,将加载并解析ivigenerator
功能文件中的QFACE_SOURCES
变量,就像在正常的qmake项目中处理SOURCES
变量一样。
然而,使用CONFIG
变量激活qmake功能有一个缺点:如果此功能不可用,则不会报告任何错误。但是,您可以使用以下附加代码来报告错误
QT_FOR_CONFIG += ivicore !qtConfig(ivigenerator): error("No ivigenerator available")
项目文件的其他部分是一个普通的库设置,应在Linux、macOS和Windows上正常工作。
后端模拟插件
由于frontend
库使用动态后端系统,我们需要相应的backend
插件,以便库提供某些功能。为了生成名为“模拟器后端”的备份插件,您可以使用与frontend
库相同的IDL文件中的backend_simulator
模板。qmake集成方式相同,但它使用QFACE_FORMAT
变量来告诉ivigenerator
使用不同的生成模板。
CONFIG += ivigenerator plugin QFACE_FORMAT = backend_simulator QFACE_SOURCES = ../example-ivi-climate.qface PLUGIN_TYPE = qtivi PLUGIN_CLASS_NAME = ClimateSimulatorPlugin
由于我们想生成一个插件而不是普通的库,我们通过将plugin
添加到CONFIG
变量中来指示qmake这样做。为了正确编译插件,它需要从前创建的库中获取后端接口头文件。然而,此头文件不是我们的源代码树的一部分,而是构建树的一部分,因为它也会被生成。我们通过以下结构将其添加到包含路径中
INCLUDEPATH += $$OUT_PWD/../frontend
backend_simulator
模板利用了之前所解释的@config_simulator注释。这意味着生成的后端提供了注释中定义的默认值,并使用minimum/maximum
或range
注释来检查新值的界限。
使用zones
注释,生成的后端提供了每个区域的单个值,并将可用的区域与前端库通信。更多信息,请参阅气候控制系统QML示例。
演示应用程序
演示应用程序提供了一个简单的QML界面,其中包括生成的界面的所有属性。
由于我们没有提供QML插件,因此该应用程序需要链接到生成的 frontend 库,并调用模块单例中生成的ClimateModule::registerTypes
和ClimateModule::registerQmlTypes
方法,这些方法将所有自动生成的接口和类型注册到QML引擎中。
在我们的QML应用程序中,我们仍然需要使用与IDL文件中相同的模块URI来导入模块。之后,该接口可以像常规的QML项目一样实例化。
import Example.IVI.Climate 1.0 Window { visible: true width: 640 height: 480 title: qsTr("QtIVI Climate") UiClimateControl { id: climateCtrl } Column { anchors.fill: parent anchors.margins: 5 Text { text: "Air Conditioning: " + climateCtrl.airConditioning } ...
我们的应用程序不了解我们的后端插件,因此,我们需要将此插件放置在我们的应用程序查找插件的目标文件夹中。默认情况下,Qt在其安装目录的plugins文件夹或应用程序当前工作目录中查找。要找到QtIvi插件,它们需要被放置在qtivi子文件夹中。
为确保此操作自动完成,我们将在我们的后端项目文件中添加以下行
DESTDIR = ../qtivi
©2020 Qt公司有限公司版权所有。本文件中包含的文档贡献权归各自的所有者所有。本文件中提供的文档是根据自由软件基金会发布的、经修改的GNU自由文档许可协议版本1.3条款授权的。Qt及其相关标志是芬兰及其它地区的Qt公司的商标。所有其他商标归各自的所有者所有。