2

I have two items that are stacked. Both items have a semi-transparent background. The circle now shows the the rounded rect below.

Stacked Opacity

Is there any way I can hide the part of the long rounded rect that overlaps with the circle? Maybe changing the parent, that the background of the circle is pulled from the ancestor higher up, and therefore ignoring the rect immediately below it?

Here is the code:

Item
{
    id: choice1
    width: 300
    height: 100

    Rectangle
    {
        id: choiceLabel1
        width: 0
        height: parent.height / 1.5
        radius: parent.height * 0.5
        color: "#88808080"
        anchors
        {
            verticalCenter: choice1.verticalCenter
            left: choice1.left
            leftMargin: choiceIcon1.width / 2
        }
        border
        {
            width: 2
            color: "red"
        }
    }
    Rectangle
    {
        id: choiceIcon1
        width: choice1.height
        height: choice1.height
        radius: width * 0.5
        color: "#88808080"
        anchors
        {
            verticalCenter: choice1.verticalCenter
            left: choice1.left
        }
        border
        {
            width: 2
            color: "red"
        }
    }
}
jpnurmi
  • 5,716
  • 2
  • 21
  • 37
goocreations
  • 2,938
  • 8
  • 37
  • 59
  • 1
    Isn't let the users see _what's behind_ the final purpose of the opacity when used this way? – skypjack Jun 11 '16 at 12:06
  • The long rectangle doesn't show up and your code doesn't run due to missing types. – Mitch Jun 11 '16 at 12:48
  • Possible duplicate of [QML Opacity Inheritance](http://stackoverflow.com/questions/9204226/qml-opacity-inheritance) – peppe Jun 11 '16 at 14:52
  • No, not the same problem. Here the opacity is nor inherited. I want to control which elements are visible underneath the opacity. – goocreations Jun 11 '16 at 15:05
  • 2
    There's no simple way rather than defining your custom geometry or doing your own painting. The solution in that other link can be partially applied here, however -- set `layer.enabled: true` on the Item that wraps both rectangles, setting an opacity on that Item, and remove the opacity on the individual rectangles. – peppe Jun 11 '16 at 19:30
  • @peppe Why don't you just post this as the answer? :) This is the solution to the problem. – Filip Hazubski Jun 13 '16 at 07:32
  • This will solve the background problem, but the border still shows through. – goocreations Jun 13 '16 at 13:25

1 Answers1

5

A solution, albeit a bit hacky would be to implement your own QML MultiRectangle component, which allow to set an opacity and draw a border around a bunch of QML Rectangle

MultiRectangle.qml

import QtQuick 2.0

Item
{
    id: root
    layer.enabled: true

    property int borderWidth: 2
    property color borderColor

    Component
    {
        id: rectangle
        Rectangle{}
    }

    Component.onCompleted:{
        var temp = children.length
        for(var i=0; i<temp; i++)
            rectangle.createObject(this,
                {
                    "z":-100,
                    "anchors.centerIn": children[i],
                    "color": borderColor,
                    "width": children[i].width+borderWidth*2,
                    "height": children[i].height+borderWidth*2,
                    "radius": Math.max((children[i].height+borderWidth*2)
                                       /children[i].height*children[i].radius,
                                     (children[i].height+borderWidth*2)
                                       /children[i].height*children[i].radius)
                })

    }
}

This will dynamically create a pseudo border behind the rectangles added to a MultiRectangle item.

Example

import QtQuick 2.5
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0

Window {
    id: root
    visible: true
    height: 200
    width: 400

    RadialGradient {
        anchors.fill: parent
        gradient: Gradient {
            GradientStop { position: 0.0; color: "white"}
            GradientStop { position: 0.3; color: "#444"}
            GradientStop { position: 1; color: "white"}
        }
    }

    MultiRectangle {
        anchors.centerIn: parent
        width: 300
        height: 100
        borderWidth: 2
        borderColor: "red"
        opacity: 0.5

        Rectangle {
            color: "cyan"
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            anchors.leftMargin: parent.borderWidth
            height: parent.height - 2 * parent.borderWidth
            width: height
            radius: height / 2
        }

        Rectangle {
            color: "cyan"
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.margins: parent.borderWidth
            anchors.top: parent.top
            height: 10
            width: height
            radius: height / 2
        }

        Rectangle {
            color: "cyan"
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.horizontalCenterOffset: 30
            anchors.margins: parent.borderWidth
            anchors.top: parent.top
            height: 30
            width: height
            radius: height / 2
        }

        Rectangle {
            color: "cyan"
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            anchors.leftMargin: 50
            height: parent.height * 0.6
            anchors.right: parent.right
            anchors.margins: parent.borderWidth
            radius: height / 2
        }
    }
}

Result

Screenshot of the qmlscene running the example

Note that since layer.enabled is set to true, clip is also set to true. Therefore, the border of child items too close to the MultiRectangle bounds will be clipped.