繁体   English   中英

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

[英]Zero width or height versus visible property in QML

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

一个用例示例:

我有一个项目,滑入窗口。 通过将其高度从0x并且当我将此项目从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的文本,尽管rootwidth: 0; height: 0width: 0; height: 0 width: 0; height: 0
正如dtech已经提到的那样,你可以将clip设置为true ,但这是不可取的,因为它会被传递给渲染器,渲染器渲染Item及其树,最后应用剪切 - 以单独的批处理。

如果你有类似的东西:

Item {
    Rectangle {
        anchors.fill: parent
        color: 'red'
    }
}

渲染时渲染器不会做任何额外的操作,因为它可以在与其余渲染器相同的批处理中进行处理。 然而,作为开发人员,很难说,当大小设置为0时是否可以看到某些内容。 因此,总是visible正确设置visiblevisible

我们可能只是设置

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.onStartedani.onStopped然后明确设置visiblity,但这不是声明性的 ,QML鼓励你总是努力保持声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM