3

I'm trying to achieve a simple Sliding Bar in QML. Here's a prerequisite I have to follow: no SVG images ( for some BR I cannot discuss here ).

 Rectangle {
            id: backgroundPower
            anchors.fill: parent
            color: "#a2aaae"
            radius: 50

            MouseArea {
                id: progressArea
                anchors.fill: parent

                onPositionChanged: {
                    updateValue(progressArea.mouseX)
                }
                onReleased:  {
                    updateValue(progressArea.mouseX)
                }

                onClicked: updateValue(progressArea.mouseX)
            }

            Rectangle {
                id: powerImage
                width: calculateWidth()
                radius: 100
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                anchors.top: parent.top
                LinearGradient {
                    id: defaultGradient
                    anchors.fill: parent
                    source: powerImage
                    start: Qt.point(0, 0)
                    end: Qt.point(0, powerImage.height)
                    gradient: Gradient {
                        GradientStop { position: 0.0; color: "#46c0e4" }
                        GradientStop { position: 0.50; color: "#0583ca" }
                        GradientStop { position: 0.95; color: "#fbffff" }
                        GradientStop { position: 1.0; color: "#fbffff" }
                    }
                }

Here's what I obtain with this code when the bar is at 100%: Bar at 100%

When I update the value ( mouse area events ) I change the width of the powerImage with the function:

var maxWidth = powerImage.parent.width
    var currentWidth = (maxWidth * barPercentage) / 100
    if (currentWidth >= maxWidth){
        currentWidth = maxWidth
    }

PROBLEM When the percentage of the bar reaches a low value ( like 10% ) I cannot fit the bar into the background, like this: enter image description here

you can see how the bar doesn't fin anymore. I know the problem is linked to the rectangle ( powerImage ) and its radius. But I don't know how to fix this. Clearly with a SVG it's really simple but in this case, I cannot use this. Is there a way to show the bar when it's only inside the background rectangle?

Cœur
  • 37,241
  • 25
  • 195
  • 267
sgrumo
  • 615
  • 2
  • 8
  • 24

1 Answers1

2

Unfortunately it is not possible to use clip: true on non-rectangular regions.

But following this answer, you can use an OpacityMask:

Rectangle {
    id: backgroundPower
    anchors.fill: parent
    color: "#a2aaae"
    radius: 50

    MouseArea {
        // ...
    }
}

Item {
    anchors.fill: backgroundPower
    layer.enabled: true
    layer.effect: OpacityMask {
        maskSource: backgroundPower
    }

    Rectangle {
        id: powerImage
        // ...
    }
}

Result:

enter image description here

But as mentionned in the answer:

But using it will be GPU consuming task as the inner item and mask have to be drawn on buffer first and then redrawn on window, so not very good for old mobile or weak embedded devices.

augre
  • 2,011
  • 12
  • 18