Rounded button with progress background fill
-
Hi,
I would like to create a count-down button with rounded corners and a background that fills/empties proportionally to the elapsed time. Something like this:
I thought I could do this using two rectangles as the button background where the black one has a width proportional to the time and the corners on the left would be clipped by the other Rectangle. Something like this:
Button{ id: control ... background: Rectangle { id: backgroundRect implicitWidth: 100 implicitHeight: 60 radius: height / 2 anchors.fill: parent color: "gray" Rectangle{ id: progressRect anchors.verticalCenter: backgroundRect.verticalCenter anchors.left: backgroundRect.left clip: true height: backgroundRect.height width: relativeCounter*backgroundRect.width color: "black" } } }
However the clipping works only along the bounding box, i.e. the corners on the left are not rounded:
I tried OpacityMask in the GraphicalEffects module, but I think I cannot use the parent rectangle as mask. I tried to work around it but could not get it to run. The last option I see is using Canvas and describing the round corners mathematically.
I am new to QML so it is quite possible that I did something wrong in the steps I tried or that I am missing a simpler option.
If anyone has an idea how it should work or can confirm that something does not work, I am grateful for any help.
Thanks in advance
-
@markugra said in Rounded button with progress background fill:
I tried OpacityMask in the GraphicalEffects module, but I think I cannot use the parent rectangle as mask.
exactly, you need to place the button and the rectangle "beside the button on the same level"
You could group the button and the rectangle into a custom component then.
See the example in the docs and replace it analogous with your button and rectangle elements. -
Thanks, I tried the OpacityMask again as you suggested and it works now. It took me a bit to get it right, because i) I had a warning about the recursive property in ShaderEffectSource needing to be set to "true" and ii) the mask size needs to be the same as the source size for it to work properly. After a while I noticed that i) originated from some code in the contentItem of the button using the ColorOverlay (in fact it was the same problem there i.e. I tried to apply it to the parent). To fix ii) I used a transparent frame so that the code now looks something like:
background: Item{ width: control.width height: control.height Rectangle{ id: progressFrame anchors.fill: parent color: "transparent" visible: false Rectangle{ id: progressRect width: 0.7*parent.width height: parent.height anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left color: "green" } } Rectangle { id: backgroundRect anchors.fill: parent radius: height / 2 color: "red" visible: true } OpacityMask{ anchors.fill: progressFrame source: progressFrame maskSource: backgroundRect } }
Resulting in:
Thanks again!