将QML编译为C++:修复非限定访问

Compiling QML to C++: Fixing unqualfied access

将QML编译为C++:修复非限定访问

Wednesday July 13, 2022 by Ulf Hermann | Comments

​2022年7月13日星期三,乌尔夫·赫尔曼评论

This is the eighth 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. We're going to learn how to avoid unqualified access now.

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

You will see quite a few warnings on unqualified access when compiling Qt Creator with qmlsc enabled. An access to a name in QML is called "unqualified" if the name is neither found in the directly surrounding QML scope, nor an ID or a type name. Usually this means you're accessing members of the root element of a component, context properties, or undeclared signal parameters. Most of those are easy to fix. Let's look at the TimeMarks.qml file in the tracing library. It implements the time marks you see above the timeline view in the QML profiler and Performance Analyzer. In line 72, we get:

在启用qmlsc的情况下编译Qt-Creator时,您将看到许多关于非限定访问的警告。如果在直接围绕的QML作用域中找不到名称,也找不到ID或类型名,则对QML中名称的访问称为“非限定”。通常这意味着您正在访问组件根元素的成员、上下文属性或未声明的信号参数。其中大多数很容易修复。让我们看看跟踪库中的TimeMarks.qml文件。它实现了您在QML探查器和性能分析器中的时间线视图上方看到的时间标记。在第72行中,我们得到:

Warning: TimeMarks.qml:72:17: Unqualified access

The line in question is simply:

这句话很简单:

target: model

What does this mean? The model we want here is the one from the surrounding element. When interpreting this code, the QML engine will retrieve properties from he outermost element in the current scope without qualification. This concept is surprisingly complex as you can open extra scopes in various ways and those will interfere with your lookup. The compiler won't let you do this. Avoiding such lookups will not only make your code compile to C++ but will also make it more readable. So, let's just rewrite this to explicitly pick the model from the object we mean:

这是什么意思?我们想要的模型是来自周围元素的模型。在解释此代码时,QML引擎将无条件地从当前范围内的最外层元素检索属性。这个概念令人惊讶地复杂,因为您可以以各种方式打开额外的作用域,这些会干扰您的查找。编译器不允许您这样做。避免此类查找不仅会使代码编译为C++,而且会使其更具可读性。那么,让我们重写它,明确地从对象中选取模型,我们的意思是:

target: timeMarks.model

What does that win? When profiling Qt Creator the usual way the binding is run 26 times here. Without the optimization we get a total time of 38.1µs. With the optimization it's 29.8µs.

那会赢什么?当分析Qt-Creator时,通常会在这里运行26次绑定。在没有优化的情况下,我们得到的总时间为38.1µs。优化后的总时间为29.8µs。

The same problem, the model being accessed in an unqualified way, is repeated several times in the same file. You can fix them all the same way. In order to access the timeMarks object inside the repeater, you have to add the following to the start of the file:

同样的问题,以非限定的方式访问模型,在同一个文件中重复多次。你可以用同样的方法修复它们。为了访问重复器内的timeMarks对象,必须在文件开头添加以下内容:

pragma ComponentBehavior: Bound

This makes sure that the delegate passed to the repeater is only instantiated in the context it's defined in. This way the compiler can guarantee that the "timeMarks" ID is actually available there. You can retrieve the delegate from the repeater, and try to instantiate it in a different place. With the above pragma, this will result in an error.

这确保传递给重复器的委托仅在其定义的上下文中实例化。通过这种方式,编译器可以保证“timeMarks”ID实际上在那里可用。您可以从重复器中检索委托,并尝试在其他位置实例化它。使用上述pragma,这将导致错误。

Then, however, we have a slightly different situation with the same warning:

然而,我们有一个稍微不同的情况,有相同的警告:

Warning: TimeMarks.qml:89:26: Unqualified access

Looking at the code, we see:

查看代码,我们可以看到:

color: ((index + (timeMarks.startOdd ? 1 : 0)) % 2)
        ? Theme.color(Theme.Timeline_BackgroundColor1)
        : Theme.color(Theme.Timeline_BackgroundColor2)

This is not the model, but rather the index injected into the context by the surrounding Repeater element. How can we qualify that one? We cannot really specify the place it comes from because it's not strictly a property. The repeater creates it on the fly for each object it creates. qmlsc does not know what it is because Repeater is not a built-in type and we cannot hardcode the context manipulations each possible type may do into the compiler. However, Repeater, like all of our view types that create delegates, has a different, better mode of operation: You can specify the data it should inject as "required" properties on the component it uses to create the delegates. Then the index is a property and we can access it as such. So let's add a required property to the "scaleItem" Rectangle:

这不是模型,而是由周围的Repeater元素注入上下文的索引。我们怎样才能证明这一点?我们不能真正指定它来自哪里,因为严格来说它不是一个属性。重复器为其创建的每个对象动态创建它。qmlsc不知道它是什么,因为Repeater不是内置类型,我们无法将每种可能的类型可能执行的上下文操作硬编码到编译器中。然而,与我们所有创建委托的视图类型一样,Repeater有一种不同的、更好的操作模式:您可以将它应该注入的数据指定为它用于创建委托的组件上的“必需”属性。然后索引是一个属性,我们可以访问它。因此,让我们向“scaleItem”矩形添加一个必需的属性:

required property int index

This way, the warning indeed disappears. Now that there are no more warnings, the binding is compiled to C++. The color binding is called fairly often, 163 times if you just load the example trace we've saved in the first post. Without the required property it takes 804µs in total, of which 718µs are spend on executing the JavaScript. With the required property we get 654µs and 596µs.

这样,警告确实消失了。现在没有更多的警告,绑定被编译为C++。颜色绑定调用得相当频繁,如果您只加载我们在第一篇文章中保存的示例跟踪,则调用了163次。如果没有所需的属性,总共需要804µs,其中718µs用于执行JavaScript。根据所需特性,我们得到654µs和596µs。

Compatibility

兼容性

QML has always supported qualifying access to properties with IDs and it's always been a good idea. Required properties were introduced in Qt 5.15.0. The ComponentBehavior pragma is quite new. It will be released with Qt 6.4.

QML始终支持使用ID对属性进行限定访问,这一直是一个好主意。Qt 5.15.0中介绍了所需的属性。ComponentBehavior pragma是一个非常新的标记。它将与Qt 6.4一起发布。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值