0

Problem statement

Can I make an item be rendered when an ancestor of it has opacity 0?


Motivation

The motivation for this question is this other question of mine (I'll call it the "hidden-texture-source" problem). Note that currently I'm using opacity: 0 rather than visible: false, but this causes the same problem as in the linked question.

The reason I'm hiding items is this.

At one point, I was only culling directly each item that needs to be used as a texture source. So the fix for the hidden-texture-source problem was simple: (simplified pseudocode)

texSourceItem.opacity = 1;
cppItem.update(); // QQuickFramebufferObject
texSourceItem.opacity = 0; // reset back to 0

But now I'm also culling entire Rows of such items. And since opacity is inherited, if I want to update the cppItem, I have to do the unhide-hide dance for the entire parent Row. Then, two texture-source items may happen do the unhide-hide procedure with interlocked timing, so to avoid bugs, I have to keep a custom reference counter that knows how many cppItems are currently being updated. This is too complicated a solution for my liking. So an answer to my question would be beneficial.

Community
  • 1
  • 1
Stefan Monov
  • 11,332
  • 10
  • 63
  • 120

1 Answers1

0

To quote from the documentation:

When this property is set, the specified opacity is also applied individually to child items. This may have an unintended effect in some circumstances. For example in the second set of rectangles below, the red rectangle has specified an opacity of 0.5, which affects the opacity of its blue child rectangle even though the child has not specified an opacity.

But you probably knew that.

I don't exactly understand what your situation exactly is, but the only solution I can see, is to make the Items to be no descendant of the transparent Item but rather it's sibling instead.

Of course, then you can't anchor to the Items (grand)*child, but you may still map their positions. (Be careful with the issue though, that mapTo/FromItem() might be complicated to update, if the position changes)

If we have e.g this situation:

Rectangle {
    id: rect1
    color: 'red'
    anchors.fill: parent

    Rectangle {
        id: rect2

        width: 200
        height: 200
        color: 'blue'
        anchors.centerIn: parent
        Rectangle {
            id: rect3
            width: 50
            height: 50
            color: 'green'
            anchors.centerIn: parent
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: parent.opacity = !parent.opacity
    }
}

But we want to keep rendering rect2 we can do this:

ShaderEffectSource {
    sourceItem: rect2
    sourceRect: Qt.rect(-rect2.x, -rect2.y, rect1.width, rect1.height)
    anchors.fill: rect1
}

For rect3 it becomes unhandy, as we now need to keep track of the relative position. (To have it dynamic, see the link posted before)

ShaderEffectSource {
    sourceItem: rect3
    sourceRect: Qt.rect(-rect2.x - rect3.x, -rect2.y - rect3.y, rect1.width, rect1.height) // keep track of all positions -.-
    anchors.fill: rect1
}
Community
  • 1
  • 1
  • Re: the ShaderEffectSource solution: Have you tried it? I'm pretty sure that when `rect`1` has `opacity:0`, the ShaderEffectSource can't use it (or its children) as a sourceItem. Well, you don't get an error message/crash, but nothing is rendered in the ShaderEffectSource. Re: making the item a sibling: That won't work in my case, since I do want the opacity inheritance, I just don't want it to apply during the update of the cppItem. – Stefan Monov May 05 '17 at 11:50