将QML编译为C++:QtQuick控件和可选导入

戚勇
2023-12-01

Compiling QML to C++: QtQuick Controls and optional imports

将QML编译为C++:QtQuick控件和可选导入

Tuesday June 21, 2022 by Ulf Hermann | Comments

​2022年6月21日星期二,乌尔夫·赫尔曼评论

This is the sixth installment in the series of blog posts on how to adjust your QML application to take the maximum advantage of qmlsc. In the first post we've set up the environment. You should read that post first in order to understand the others.

​这是关于如何调整QML应用程序以最大限度地利用qmlsc的博客文章系列的第六部分。在第一篇文章中,我们设置了环境。为了理解其他人,你应该先读那篇文章。

This time I will show how to deal with the optional imports provided by Qt's own modules. When compiling any QML file that imports QtQuick.Controls you are greeted with a message of this kind:

这次我将展示如何处理由Qt自己的模块提供的可选导入。编译导入QtQuick.Controls的任何QML文件时,您将收到此类消息:

Warning: QtQuick.Controls uses optional imports which are not supported. Some types might not be found.

Indirectly, among other problems, this leads to:

除其他问题外,这间接导致:

Warning: CategoryLabel.qml:145:9: unknown grouped property scope anchors.
    anchors.verticalCenter: txt.verticalCenter

As qmlsc doesn't know the QtQuick.Controls types, it doesn't know they provide anchors. This one is an ImageToolButton, derived ToolButton as probided by QtQuick.Controls. As qmlsc doesn't know the type of the property the binding is assigned to, it cannot compile the binding.

因为qmlsc不知道QtQuick.Controls类型,它不知道它们提供了锚。这是一个ImageToolButton,QtQuick.Controls的派生ToolButton。由于qmlsc不知道为其分配绑定的属性的类型,因此无法编译绑定。

Profiling using QML Profiler reveals that the 26 calls calls to the binding on anchors.verticalCenter take 54.2µs, of which 29.5µs are spent on JavaScript execution.

使用QML探查器进行分析显示,26个调用调用了anchors.verticalCenter的绑定。需要54.2µs,其中29.5µs用于JavaScript执行。

What does the warning mean? QtQuick.Controls uses different styles, depending on your platform. On windows it usually uses a "windows" style, on macOS a "macOS" style, etc. However, you can override the automatic style selection at run time using the QT_QUICK_CONTROLS_STYLE environment variable, via a configuration file, and in a number of other ways. This means, when QtQuick.Controls is imported, qmlsc does not know what types it will provide. It could be the types from either of the styles available.

警告是什么意思?QtQuick.Controls使用不同的样式,具体取决于您的平台。在windows上,它通常使用“windows”样式,在macOS上使用“macOS”样式等。但是,您可以在运行时使用QT_QUICK_CONTROLS_STYLE环境变量、通过配置文件以及其他多种方式覆盖自动样式选择。这意味着,当QtQuick.Controls已导入,qmlsc不知道它将提供什么类型。它可以是任何可用样式中的类型。

We can fix this by nailing down the style to be used at compile time. Since our Timeline module uses QtQuick.Controls practically everywhere, the easiest way to do it is to just import the specific style we want to use from the module definition in the CMakeLists.txt. There we can use CMake to choose a different style depending on platform or other criteria we may need. We change our module as follows and drop all the QtQuick.Controls imports from the individual QML files:

我们可以通过确定编译时要使用的样式来解决这个问题。因为我们的Timeline模块使用QtQuick.Controls实际上无处不在,最简单的方法就是从CMakeLists.txt中的模块定义中导入我们想要使用的特定样式。在那里,我们可以使用CMake根据平台或其他可能需要的标准选择不同的样式。我们将模块更改如下,并删除所有QtQuick.Controls从各个QML文件的导入:

if(WIN32)
  set(QUICK_CONTROLS "QtQuick.Controls.Windows")
elseif(APPLE)
  set(QUICK_CONTROLS "QtQuick.Controls.macOS")
else()
  set(QUICK_CONTROLS "QtQuick.Controls.Basic")
endif()

qt_add_qml_module(Tracing
  URI "QtCreator.Tracing"
  VERSION "1.0"
  NO_PLUGIN
  DEPENDENCIES
    QtQuick
  IMPORTS
    ${QUICK_CONTROLS}
  QML_FILES
    ${TRACING_QML_FILES}
  RESOURCES
    ${TRACING_QML_RESOURCES}
  SOURCES
    ${TRACING_CPP_SOURCES}
)

In reality, we cannot do this to Qt Creator because people value the choice they have in customizing Qt Creator's look and feel to whatever desktop environment they are using. If you are developing a commercial application that tightly controls its look and feel, and possibly ships its own style, you may want to fix the style at compile time anyway, though. In that case, you can reap the benefits of compiling the QML code that uses it to C++ in addition.

事实上,我们不能对Qt Creator这样做,因为人们很重视根据自己使用的桌面环境定制Qt Creator外观的选择。如果您正在开发一个严格控制其外观和感觉的商业应用程序,并且可能提供自己的样式,那么您可能希望在编译时修复该样式。在这种情况下,您还可以获得将使用它的QML代码编译为C++的好处。

After applying this change, the binding on anchors.verticalCenter can be compiled to C++. Now the 26 calls take 29µs, of which 13.7µs are spent on JavaScript execution. That's a rather significant improvement from the 54.1µs and 29.5µs we've seen before.

应用此更改后,anchors.verticalCenter的绑定。可以编译为C++。现在,26个调用需要29µs,其中13.7µs用于JavaScript执行。这比我们之前看到的54.1µs和29.5µs有了相当大的改进。

Compatibility

兼容性

Module-level imports have been available since Qt 5.14, but before Qt 6 they have a number of flaws. First, in Qt 5 you don't get to use qt_add_qml_module(). Therefore you have to write your qmldir files manually or better, write your own build system code to generate them. Then, the qmldir "import" directive in Qt 5 will only behave reasonably if:

​模块级导入自Qt 5.14起就可用,但在Qt 6之前,它们有许多缺陷。首先,在Qt 5中,不能使用qt_add_qml_module()。因此,您必须手动或更好地编写qmldir文件,编写自己的构建系统代码来生成它们。那么,Qt 5中的qmldir“import”指令只有在以下情况下才能正常运行:

1.The module in question also declares some QML types itself.

1.所讨论的模块本身也声明了一些QML类型。

2.All of the other types are C++-based (not .qml files).

2.所有其他类型都是基于C++的(不是.qml文件)。

3.The module has a plugin. You cannot directly compile it into your application.

3.模块有插件。您不能直接将其编译到应用程序中。

 类似资料: