[英]Zero width or height versus visible property in QML
将组件的width
或height
设置为零与将其visible
属性设置为false
具有相同的效果吗?
一个用例示例:
我有一个项目,滑入窗口。 通过将其高度从0
为x
并且当我将此项目从x
关闭为0
时,可以进行滑动。 不想深入了解为什么我没有动画项目的位置。 当项目的高度为0时,我应该将其visible
属性设置为false
还是没有任何区别?
不是真的,除非你剪辑。 最好尽可能避免剪裁。
零大小的Item
仍会显示其子项。
将visible设置为false将隐藏整个对象树。
在您的特定情况下,只要它不会导致您有不必要的可见剩余物,它似乎无关紧要。 你当然不希望有一个像visible: height
这样的绑定,因为它会在动画的每一步都不必要地执行。
为了安全起见,您可以在动画上安装处理程序以切换可见性:
// in the animation
onStarted: if (!item.height) item.visible = true // show if start at 0
onStopped: if (!item.height) item.visible = false // hide if end at 0
如果您直接将可见性绑定到高度,这将避免您获得的连续重新评估,但仍会确保在对象开始展开之前的可见性,并在完成签约后关闭。
正如dtech已经指出的那样,组件的根节点的维度不会自动表示底层对象树的维度。 举个例子吧:
Item {
id: root
Text {
id: txt
text: 'some text produces implicit width'
}
}
在这个例子中,将显示txt
的文本,尽管root
的width: 0; height: 0
是width: 0; height: 0
width: 0; height: 0
。
正如dtech已经提到的那样,你可以将clip
设置为true
,但这是不可取的,因为它会被传递给渲染器,渲染器渲染Item
及其树,最后应用剪切 - 以单独的批处理。
如果你有类似的东西:
Item {
Rectangle {
anchors.fill: parent
color: 'red'
}
}
渲染时渲染器不会做任何额外的操作,因为它可以在与其余渲染器相同的批处理中进行处理。 然而,作为开发人员,很难说,当大小设置为0
时是否可以看到某些内容。 因此,总是visible
正确设置visible
是visible
。
我们可能只是设置
visible: width > 0 && height > 0 && opacity > 0
只要我们不在任何属性上制作动画或经常更改它们,它就可以正常工作。 至少对于动画,我们可能具有良好的知识,当任何这些属性可能变为0
并使用此信息来减少评估量。
关于QML的好处是,逻辑表达式是从左到右计算的,这意味着在我们的上一个例子中:
width === 0
并且height
发生变化,则不会触发重新评估 height === 0
并且width
发生变化,则每次更改都会触发重新评估。 这意味着,我们需要先把最稳定的条件。 这可能是我们关于何时这些值可能会发生变化的信息 。 我建议使用animation.running
属性,以防止在动画运行时重新评估绑定。
让我们看一个更完整的例子:点击后,这个Rectangle
将从width: 800
缩小到width: 0
- 这将使它不可见。
或者将另外三个属性binding1, binding2, binding3
绑定到表达式,我们可以使用它们来设置visible
。 当重新绑定特定部分的绑定时,我们会记录下来。
Rectangle {
id: rect
color: 'red'
width: 800
height: 600
NumberAnimation {
id: ani1
target: rect
property: 'width'
from: 800
to: 0
duration: 3000
}
}
MouseArea {
anchors.fill: parent
onClicked: ani1.running = true
}
property bool binding1: {console.log("1", !rect.width); return !rect.width}
property bool binding2: {!ani1.running && (function() { console.log("2", !rect.width); return !rect.width })()}
property bool binding3: {(function() { console.log("3", !rect.width); return !rect.width })() && !ani1.running}
// equivalent, stripped of the logging:
// property bool binding1: !rect.width
// property bool binding2: !ani1.running && !rect.width
// property bool binding3: !rect.width && !ani1.running
正如我们所看到的,当宽度发生变化时,不断重新评估binding1
。 这是不可取的。
我们可以看到, binding2
仅在创建时评估一次,并且每当ani
停止运行时。
在binding3
我们有另一种方式,我们首先评估width
,然后是ani
是否正在运行。 这意味着,只要width
发生变化,我们就会重新评估。
我们也可以使用信号处理程序ani.onStarted
和ani.onStopped
然后明确设置visiblity,但这不是声明性的 ,QML鼓励你总是努力保持声明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.