Reputation: 117
I am creating a custom style in QML and would like to have an indeterminate progress bar that looks like this, a rounded background with a rounded bar on the inside that moves from left to right.
The trouble I'm having is with behavior when the bar reaches the end. Using just the clip
property causes the rounded bar to become square when in contact with the edge.
Rectangle {
id: bg
color: "black"
width: 120; height: 8; radius: 4; x: 100; y: 50
clip: true
Rectangle {
id: bar
color: "orange"
width: 60; height: 8; radius: 4
NumberAnimation on x {
running: true
from: -(bar.width * 1.2 )
to: bg.width * 1.2
loops: Animation.Infinite
duration: 1000
}
}
}
This is because clip
uses the bounding rectangle of the parent object. Fair enough.
I next tried using a MultiEffect
(I'm using Qt6 so no OpacityMask
) to apply to the bar, however after some experimenting I found that the masking properties of the MultiEffect do not take into account the position of the maskSource so this didn't work.
MultiEffect {
source: bar
anchors.fill: bar
maskEnabled: true
maskSource: bg
}
How can I achieve the desired behavior, ie having the bar be clipped by the background which has rounded corners?
I'm aware I can achieve a similar effect by growing and shrinking the bar's width when at the respective edges but I would like to avoid this if possible.
Upvotes: 0
Views: 348
Reputation: 26214
First point, there is OpacityMask
in Qt6, but it is under Qt5Compat.GraphicalEffects
.
Second point, the problem is solvable with the Qt6 MultiEffect
. The pain point is the maskSource
must be specified slightly different than the OpacityMask
equivalent with a necessary Item
to create the layering.
The animation bar
needs to be updated to contain both the black background and the animating bar.
[EDIT]
For improved anti-aliasing, let's put (1) enable clip and radius in the source
, (2) however, turn OFF antialiasing in the maskSource
.
Rectangle {
id: barWithBackground
width: 120; height: 8; x: 100; y: 50; radius: 4
clip: true
visible: false
color: "black"
Rectangle {
id: bar
color: "orange"
width: 60; height: 8; radius: 4
NumberAnimation on x {
running: true
from: -(bar.width * 1.2 )
to: barWithBackground.width * 1.2
loops: Animation.Infinite
duration: 1000
}
}
}
// OpacityMask
// Qt5.* from QtGraphicalEffects
// Qt6.* from Qt5Compat.GraphicalEffects
// OpacityMask {
// source: barWithBackground
// anchors.fill: barWithBackground
// maskSource: roundedRectangleMask
// }
// Since Qt6.5
MultiEffect {
source: barWithBackground
anchors.fill: barWithBackground
maskEnabled: true
maskSource: roundedRectangleMask
}
Item {
id: roundedRectangleMask
width: 120; height: 8
layer.enabled: true
visible: false
Rectangle {
color: "black"
width: 120; height: 8; radius: 4
antialiasing: false
}
}
Upvotes: 2