Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Make a round progress bar



  • Hello,

    I would like to make a round progress bar close to that :
    0_1528977088308_08a3b18e-10e0-4860-aefb-9ee4dd2af36e-image.png

    I don't know how to achieve this. Does anybody can give me clue about how to start at least ?

    Thanks in advance


  • Moderators

    I guess something like this could work:

    Rectangle {
      property int value: 0
      width: 300
      height: width
      border.width: 5
      radius: width * .5
      clip: true
    
      Rectangle {
        with: parent.width
        height: parent.height * parent.value / 100 // percentage
        color: "#ff0000"
      }
    }
    

    Untested.



  • @sierdzio said in Make a round progress bar:

    Rectangle {
    property int value: 0
    width: 300
    height: width
    border.width: 5
    radius: width * .5
    clip: true

    Rectangle {
    with: parent.width
    height: parent.height * parent.value / 100 // percentage
    color: "#ff0000"
    }
    }

    It is not working here is the result : 0_1528980128037_e9ce0a98-f955-49b7-9c35-9dd36530cd83-image.png
    I tried something close to this but I have'nt been able to get the same shape as the parent rectangle.



  • @DavidM29 said in Make a round progress bar:

    with: parent.width

    That should obviously be:
    width: parent.width
    ....


  • Moderators

    OK then one more try and I'll recommend something else.

    Item {
      id: main
      property int value: 0
      width: 300
      height: width
    
      Rectangle {
        width: parent.width
        height: parent.height * parent.value / 100 // percentage
        color: "#ff0000"
        anchors.bottom: parent.bottom
      }
    
      Rectangle {
        anchros.fill: parent
        border.width: 5
        radius: width * .5
        clip: true
      }
    }
    

    I suppose the renctangle will still stick out, though. You could achieve your goal using QML Canvas, custom QQuickItem painting.



  • @sierdzio here is the result : 0_1528981120882_e09a41d0-53ee-4ee6-b99a-1128d1d126bf-image.png

    Never used Canvas or QuickItem painting. Can you guide me a bit through this ?



  • @DavidM29

    The clip effect is based on rectangle, so, you can reimplement this effect in paint render (c++) or you can use a "rectangle" (item) to shape the inner circle.

       Rectangle{
            property int percentage: 100
            id: root
            width: 300
            height: 300
            radius: width / 2
    
            color: "white"
            border.color: "#385d8a"
            border.width: 5
    
            Item{
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                anchors.right: parent.right
                height: parent.height * parent.percentage / 100
                clip: true
    
                Rectangle{
                    width: root.width - root.border.width * 2
                    height: root.height - root.border.width * 2
                    radius: width / 2
                    anchors.bottom: parent.bottom
                    anchors.left: parent.left
                    anchors.margins: root.border.width
                    color: "red"
                }
            }
    
            Text{
                anchors.centerIn: parent
                font.pixelSize: 20
                text: root.percentage.toString() + "%"
            }
        }
    


  • Works nicely ! Thank you !
    I have another question :
    For an image is it possible to do the same for example, considering this as an image : 0_1528986288161_a26de074-5e6d-4bd8-9026-f483576dfd67-image.png

    like a .svg file, would it be possible to color just the circle of the image with the same rendering ?

    If you want I can make a new post for this.



  • @DavidM29
    I believe for image you can apply a mask in the image
    This post has a good solution:
    https://stackoverflow.com/a/32710773

    Opacity Mask Documentation



  • I believe I did not express my self clearly.

    From the the image on my previous post I would like to know how to do something like that : 0_1528988622710_d44ac1e5-cc85-4650-bda8-86456d5e1ce3-image.png
    The idea is to have a variable part on the image.
    Maybe it should be separate in different step like that :
    0_1528989011848_ca971153-fdd1-4bf6-8d16-1abd16987118-image.png
    The background would be always present and the filling appear partially depending on the value.



  • @DavidM29 do you want to create an animation of loading of image starting on bottom and ending on top ?



  • I want to animated just a part of the image. I want to keep a constant part. Assuming this image : 0_1528990242450_05ee0e6a-2f07-4a6c-a1c2-3be18735717e-image.png
    I want to keep the wheel and glass but I want to animate the Orange color of the car. Loading like the circle on the previous messages.
    Not sure it is very clear. I'm trying to find a real exemple somewhere.

    Edit :

    Like here https://cdn.dribbble.com/users/100142/screenshots/2920352/loading-animation-cd-v2.gif
    There is the middle of the display animated and the rest of it is fixed. I would like to anime the display from bottom to top and keeping the border fixed.
    Or from the example above Fill my background image on the transparent circle with the red circle.



  • @DavidM29
    Something like that:

    Item{
            width: 350
            height: 150
            anchors.centerIn: parent
            Rectangle{
                id: rect
                color: "steelblue"
                width: 350
                anchors.bottom: parent.bottom
    
                SequentialAnimation{
                    running: true
                    loops: Animation.Infinite
                    NumberAnimation{
                        target: rect
                        properties: "height"
                        from: 0
                        to: 150
                        duration: 5000
                    }
                    NumberAnimation{
                        target: rect
                        properties: "height"
                        from: 150
                        to: 0
                        duration: 5000
                    }
                }
            }
        }
    


  • @KillerSmath

    Yes exactly but with a constant border wich is like an image.



  • @DavidM29
    Using the previous posts, you can use mask with rectangle loader.

    Obs: the maximum radius = min_between(width, height) / 2

    Code

    import QtQuick 2.8
    import QtGraphicalEffects 1.0
    
      Rectangle{
            property int imgRadius: Math.min(imgContainer.width, imgContainer.height) / 2
            property int borderWidth: 3
    
            id: imgContainer
            width: 190
            height: 190
            anchors.centerIn: parent
            color: "#f2f2f2"
            border.color: "#385d8a"
            border.width: borderWidth
            radius: imgRadius
    
            Image {
                id: img
                anchors.fill: parent
                source: "https://www.gnu.org/graphics/nu-gnu.svg"
                layer.enabled: true
                layer.effect: OpacityMask {
                    maskSource: Item {
                        width: imgContainer.width
                        height: imgContainer.height
                        Rectangle{
                            id: rectContainer
                            width: parent.width
                            anchors.bottom: parent.bottom
                            clip: true
                            color: "transparent"
                            Rectangle {
                                id: rectMask
                                anchors.bottom: parent.bottom
                                anchors.left: parent.left
                                anchors.right: parent.right
                                anchors.margins: imgContainer.borderWidth
                                height: img.height - imgContainer.borderWidth * 2
                                radius: Math.max(0, imgContainer.imgRadius-imgContainer.borderWidth)
                            }
                            SequentialAnimation{
                                running: img.status == Image.Ready
                                loops: Animation.Infinite
    
                                NumberAnimation{
                                    target: rectContainer
                                    properties: "height"
                                    from: 0
                                    to: img.height
                                    duration: 5000
                                }
                                PauseAnimation{
                                    duration: 1000
                                }
    
                                NumberAnimation{
                                    target: rectContainer
                                    properties: "height"
                                    from: img.height
                                    to: 0
                                    duration: 5000
                                }
    
                                PauseAnimation{
                                    duration: 1000
                                }
                            }
                        }
                    }
                }
            }
        }
    

    0_1529001399131_gggg.gif

    Full Code Link - Git Hub



  • That is close to what I want but this will work only on standard shape like rectangle or circle. If I wan't to have this effect inside an image it will not work doesn't it ?


Log in to reply