我以为ScrollBar.vertical是bool的变种,但是为什么冒号后面有个对象ScrollBar { id: scrollBar }呢?
答案很简单,因为ScrollBar.vertical 既不是布尔值也不是变体,而是ScrollBar 的类型。这在文档中有说明。
ScrollBar.vertical : ScrollBar
此属性将垂直滚动条附加到 Flickable。
Flickable {
contentHeight: 2000
ScrollBar.vertical: ScrollBar { }
}
注意副标题告诉我们冒号后面的类型:ScrollBar。
有没有关于这种语法的文档?
是的,有。我从this page复制了以上内容。
使用 [...] 有什么区别
我将遍历每一行令人困惑的代码,并用它的名字标记每一行。
// Attached Property
ScrollBar.vertical: ScrollBar { id: scrollBar }
// Child Object
ScrollBar { id: scrollBar; orientation: Qt.Vertical }
// Grouped Property
anchors.fill: parent
让我们一一来看看。
附加属性
附加属性 [...] 是一种机制,可以使用对象无法使用的额外属性或信号处理程序来注释对象。特别是,它们允许对象访问与单个对象特别相关的属性或信号。
对附加属性的引用 [...] 采用以下语法形式:
<AttachingType>.<propertyName>
例如,ListView 类型有一个附加属性 ListView.isCurrentItem,ListView 中的每个委托对象都可以使用该属性。每个单独的委托对象都可以使用它来确定它是否是视图中当前选定的项目:
import QtQuick 2.0
ListView {
width: 240; height: 320
model: 3
delegate: Rectangle {
width: 100; height: 30
color: ListView.isCurrentItem ? "red" : "yellow"
}
}
在这种情况下,附加类型的名称是ListView,而有问题的属性是isCurrentItem,因此附加的属性称为ListView.isCurrentItem。
(source)
在我们的特定情况下,ScrollBar 是 附加类型,vertical 是 属性。
请记住,ListView.isCurrentItem 和 ScrollBar.vertical 之间存在一些差异。前者是bool 类型,而后者是ScrollBar 类型。此外,前者是read-only 属性,这意味着我们无法分配或更改它。另一方面,您可以分配给ScrollBar.vertical。
如果ListView.isCurrentItem 不是只读,我们可以像使用ScrollBar.vertical 一样分配它。
delegate: Rectangle {
ListView.isCurrentItem: true
}
但由于它是只读的,因此会引发错误。
子对象
这是 QML 基础知识。这是一个例子:
ApplicationWindow {
visible: true
width: 800; height: 600
// child object of ApplicationWindow
Rectangle {
width: 200; height: 200
color: "red"
// child object of Rectangle
Text { text: "Hello World" }
}
// child object of ApplicationWindow
Rectangle {
x: 400
width: 200; height: 200
color: "blue"
}
}
回头看ScrollBar:
Flickable {
ScrollBar { id: scrollBar; orientation: Qt.Vertical }
}
这将实例化一个子对象ScrollBar,仅此而已。没有添加功能。
分组属性
在某些情况下,属性包含一组逻辑子属性属性。可以使用点表示法或组表示法来分配这些子属性属性。
例如,Text 类型具有字体组属性。下面,第一个 Text 对象使用点表示法初始化其 font 值,而第二个使用组表示法:
Text {
// dot notation
font.pixelSize: 12
font.b: true
}
Text {
// group notation
font { pixelSize: 12; b: true }
}
(source)
另一个常见的分组属性示例是anchors(您可能已经注意到)。
不要让点符号让您感到困惑。尝试找出以下两个属性之间的一般区别:
anchors.top
ScrollBar.vertical
重要的区别是属性必须以小写字母开头,而QML类型以大写字母开头。考虑到这一点,我们可以看到anchors 显然是一个属性,而ScrollBar 是一个类型。
解决了这些问题,我认为我们可以尝试再解决一个问题。
为什么使用附加属性而不是将ScrollBar 定义为子对象?
因为更好的自动化。来自文档:
当ScrollBar 垂直或水平附加到Flickable 时,其几何形状和以下属性会自动设置并酌情更新:
附加的ScrollBar 将自身重新设置为目标Flickable。垂直连接的ScrollBar 将自身调整为Flickable 的高度,并根据布局方向将自身定位到其任一侧。水平附加的ScrollBar 将自身调整为Flickable 的宽度,并将自身定位到底部。
(source)
这使您可以专注于其他事情,而不必担心滚动条的位置。
当然,将ScrollBar 实例化为子对象(非附加)也有其优点。
可以在不使用附加属性 API 的情况下创建 ScrollBar 的实例。当附加的滚动条的行为不充分或Flickable 未使用时,这很有用。 [...]
使用非附加滚动条时,必须手动完成以下操作:
- 布局滚动条(例如,使用 x 和 y 或锚属性)。
- 设置大小和位置属性以确定滚动条相对于滚动项的大小和位置。
- 设置 active 属性以确定滚动条何时可见。
(source)