Search code examples
qtqmlgradientopacitymask

QML Circular Gauge


I'm currently creating a virtual dashboard and i would like to get type of progress bar behind needle as in this link: https://forum.qt.io/topic/89307/qml-circular-gauge-styling-needle-trailing-colour-glow .

So far, I've only done needle progress bar using Canvas. I dont understand how to use conicalGradient with opacity mask to achieve the effect that I need.

import QtQuick 2.9
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0

ApplicationWindow 
{

    id:root
    visible: true
    width: 1024
    height: 600
    property int external_width: 534
    property int external_height: 533
    property bool external_reverse: false
    property int external_angle: 0
    property int externalstart_angle: 138 //138
    property int external_angle_limit: 360//264
    property int external_radius: 235
    property int external_lineWidth: 60

    Canvas {
        id: external_progress_bar
        width: root.external_width
        height: root.external_height
        x: (root.width - width)/2
        y: (root.height - height)/2
        property real angle: 260
        property real nextAngle: (Math.PI/180)*angle
        property color col: "red"
        onPaint: {
            var ctx = getContext("2d");
            ctx.reset();
            ctx.beginPath();
            ctx.arc(width/2, height/2, root.external_radius, (Math.PI/180) * root.externalstart_angle,(Math.PI/180) * root.externalstart_angle + nextAngle, root.center_reverse);
            ctx.lineWidth = root.external_lineWidth
            ctx.strokeStyle = col
            ctx.stroke()
        }
    }
}

I would be very grateful for the sample code with explanations.


Solution

  • What you can do is using a ConicalGradient and a OpacityMask.

    Create the same canvas with a different color. Then, a ConicalGradient from transparent to white and a mask to reduce the painted area to your canvas:

    Canvas {
            id: external_progress_bar
            ...
             visible: false // Not visible (it will be painted by the mask)
        }
    
        ConicalGradient {
            id: progress
                anchors.fill: external_progress_bar
                angle: 45.0 // Change this angle to move the gradient effect
                gradient: Gradient {
                    GradientStop { position: 0.0; color: "transparent" }
                    GradientStop { position: 0.1; color: "white" } // Just a part of the canvas
                }
                 visible: false // Not visible (it will be painted by the mask)
        }
        OpacityMask {
                anchors.fill: progress
                source: external_progress_bar
                maskSource: progress
                invert: true
            }
    

    You will get :

    Example

    For more explanation on OpacityMask, see the Qt documentation