Can't use ConicalGradient as Shape stroke color in Qt 6
-
I want to implement a gradient-filled Gauge using QML in Qt 6 and can't figure out how to force PathAngleArc to use gradients for stroke color:
I know that ShapePath can use gradients (fillGradient: ...) for the fill color. There is no equivalent property for strokes.
Using opacity mask on Gradient source with Shape mask does not work either.
The only working combination for masking I've been able to identify is Rectangle+Gradient (source) and Image (mask).
I was able to implement this three times before: in plain C++ using QGraphicsItem, in C++ / QML using QQuickPaintedItem and in pure QML using Qt5Compat.GraphicalEffects.
It is only Qt 6 QML version that is problematic.
Has anyone managed to implement this in pure QML for Qt 6?
This is the sample QML code I used for prototyping (non-working):
Rectangle { x: 0; y : 0 width: 500; height: 500 id: backdrop gradient: Gradient { GradientStop { position: 0.0; color: "#00ADEF" } GradientStop { position: 1.0; color: "#FFF100" } } visible: false } // Shape { // id: backdrop // visible: false // ShapePath { // fillGradient: ConicalGradient { // centerX: 250; centerY: 250 // angle: 270 // GradientStop { position: 0.0; color: "#00ADEF" } // GradientStop { position: 1.0; color: "#FFF100" } // } // strokeColor: "transparent" // startX: 0 // startY: 0 // PathLine { // x: 500 // y: 0 // } // PathLine { // x: 500 // y: 500 // } // PathLine { // x: 0 // y: 500 // } // PathLine { // x: 0 // y: 0 // } // } // } Image { id: mask x: 0 y: 0 width: 500 height: 500 source: "images/checkerboard2.png" visible: false } // Shape { // x: 0; y: 0 // width: 500; height: 500 // id: mask // visible: false // ShapePath { // id: front // capStyle: ShapePath.FlatCap // strokeWidth: 50 // fillColor: "transparent" // PathAngleArc { // centerX: backdrop.width / 2 // centerY: backdrop.height / 2 // radiusX: backdrop.width / 2 - front.strokeWidth / 2 // radiusY: backdrop.height / 2 - front.strokeWidth / 2 // startAngle: 155 // sweepAngle: 230 // } // } // } MultiEffect { id: quickMultiEffect maskEnabled: true anchors.fill: backdrop source: backdrop maskSource: mask // maskInverted: true }
Those are code snippets from working implementations:
QGraphicsItem:
void GradientGuage::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{... QConicalGradient gradient(newRec.center(), gradAngle); gradient.setColorAt(0, m_startColor); gradient.setColorAt(firstStop, m_startColor); gradient.setColorAt(secondStop, m_endColor); gradient.setColorAt(1, m_endColor); QBrush brush(gradient); m_pen.setBrush(brush); painter->setPen(m_pen); painter->drawArc(newRec, m_startAngle, valueToSpanAngle()); ...
}
QQuickPaintedItem:
void GradientGuage::paint(QPainter *painter)
{
...QConicalGradient gradient(newRec.center(), gradAngle); gradient.setColorAt(0, QColor(0, 0, 0)); gradient.setColorAt(firstStop, m_startColor); gradient.setColorAt(secondStop, m_endColor); gradient.setColorAt(1, QColor(0, 0, 0)); QBrush brush(gradient); m_pen.setBrush(brush); painter->setPen(m_pen); painter->drawArc(newRec, m_startAngle, valueToSpanAngle()); ...
}
Qt5Compat.GraphicalEffects:
// Main arc gauge Shape { id: arc anchors.fill: parent visible: false ShapePath { id: front capStyle: ShapePath.FlatCap strokeWidth: 50 fillColor: "transparent" PathAngleArc { id: pathAArc centerX: root.width / 2 centerY: root.height / 2 radiusX: root.width / 2 - front.strokeWidth / 2 radiusY: root.height / 2 - front.strokeWidth / 2 startAngle: root.startAngle sweepAngle: 0 } } } // Conical gradient stroke effect ConicalGradient { id: grad anchors.fill: arc angle: 0 gradient: Gradient { GradientStop { position: 0.0; color: "black" } GradientStop { position: internal.firstStop; color: root.startColor } GradientStop { position: internal.secondStop; color: root.endColor } GradientStop { position: 1.0; color: "black" } } source: arc }