零宽度或高度与QML中的可见属性

时间:2017-08-30 09:32:47

标签: qt qml

将组件widthheight设置为零与将visible属性设置为false的效果相同吗?

示例用例:

我有一个项目,它滑入窗口。通过将其高度从0设置为x以及当我将此项目从x关闭到0时,会发生滑动。不想深入了解为什么我没有动画项目的位置。当项目的高度为0时,我应该将其visible属性设置为false还是它没有任何区别?

2 个答案:

答案 0 :(得分:5)

不是真的,除非你剪辑。最好尽可能避免剪裁。

大小为零的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

如果您直接将可见性绑定到高度,这将避免您获得的连续重新评估,但仍会确保在对象开始展开之前的可见性,并在完成签约后关闭。

答案 1 :(得分:2)

正如 dtech 已经指出的那样,组件的根节点的维度不会自动表示基础对象树的维度。举个例子吧:

Item {
    id: root
    Text {
        id: txt
        text: 'some text produces implicit width'
    }
}

在此示例中,将显示txt的文字,但root的尺寸为width: 0; height: 0
正如已经提到的 dtech ,您可以将clip设置为true,但这不可取,因为它会传递给呈现器,呈现{{1}和它的树,最后应用剪辑 - 单独批处理。

如果你有类似的东西:

Item

渲染器在渲染时不会做任何额外的操作,因为它可以在与其余渲染器相同的批处理中进行处理。但是,作为开发人员,很难说,当大小设置为Item { Rectangle { anchors.fill: parent color: 'red' } } 时,是否可以看到某些内容。因此,始终可以正确设置0

我们可能只是设置

visible
只要我们不在任何属性上制作动画或经常更改它们,

就可以正常工作。至少对于动画我们可能有很好的知识,当任何这些属性可能成为visible: width > 0 && height > 0 && opacity > 0 并使用此信息来减少评估量。

关于QML的好处是,逻辑表达式是从左到右计算的,这意味着在我们的上一个例子中:

  • 如果0width === 0发生变化,则不会触发重新评估
  • 如果heightheight === 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发生变化,我们就会重新评估。

我们也可以使用信号处理程序widthani.onStarted然后显式设置visiblity,但这不会是声明,QML鼓励你总是努力保持declarativ。