Home > Net >  QML ProgressBar with image
QML ProgressBar with image

Time:12-07

I would like to know how to use, as progress bar, an image. Currently I use this code: `

ProgressBar {
                id: pb
                value: 0
                minimumValue:  0
                maximumValue:  100
                style: ProgressBarStyle{
                    progress: Image {
                        source: "../icons/progress_full.png"
                    }

                }

            }

`

I would like that the "progression" reveals the image. Some suggestions?

What I got currently it's a distorced image that streatches to fill the rectangle.

1° Edit: I tried to follow Stephen Quan explanation doing this: I guess I lack some points on my code =(

import QtQuick 2.3
import QtQuick.Controls 1.4 
import QtQuick.Controls.Styles 1.4
import "."

Rectangle {
    id: rectangle1
    x: 0
    y: 0
    width: 600
    height: 130
    color: "#ffd1f9"

    // -----------------
    // PROPRIETA'
    // -----------------

    // Proprietà pubbliche
    property int        val: 50
    property alias      version: textVersion.text
    property alias      textColor: textVersion.color

    // Proprietà private
    QtObject {
        id:     d
        property int        firstColumn: 0
        property int        lastColumn: 260
    }

    // -----------------
    // WIDGET
    // -----------------

    CFBrandConst {
        id: brand
    }

    // Progressbar grafica
    Item {
        id: item1
        x: 170
        width: 271
        height: 120
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter

        Image {
            id: imgEmpty
            cache: (Component.status == Component.Ready)
            x: 0
            y: -56
            width: 260
            height: 91
            property real from: 0.0
            property real to: 1.0
            property real value: 0.0
            anchors.top: parent.top
            anchors.topMargin: 0
            anchors.right: parent.right
            anchors.rightMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            fillMode: Image.TileHorizontally
            source: "../icons/progress_empty.png"

            Image {
                id: imgFull
                cache: (Component.status == Component.Ready)
                width: (to - value) / (to - from) * parent.width//260
                anchors.top: parent.top
                anchors.topMargin: 0
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 0
                anchors.left: parent.left
                anchors.leftMargin: 0
                source: "../icons/progress_full.png"
                //sourceSize: Qt.size(width, height)
                fillMode: Image.PreserveAspectFit


                onSourceChanged: {
                    onValChanged();
                }
        }
    }

    Text {
        id: textVersion
        text: qsTr("version")
        color: brand.fontColor
        font.family: brand.fontFamily
        font.pointSize: brand.fontPointSizeNormal
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        anchors.top: imgEmpty.bottom
        anchors.topMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0
        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.left: parent.left
        anchors.leftMargin: 0
        }
    }


    onValChanged: {
    //SOME TENTATIVES HERE
        val = Math.max(0, Math.min(100, val));
        //imgFull.width = (100-val)/(100)*(d.lastColumn - d.firstColumn);
        //imgFull.width = d.firstColumn   (d.lastColumn   d.firstColumn) * val / 100;
        //pb.setValue(val);
        imgEmpty.value= val;


    }
}

CodePudding user response:

You should use Image fillMode property to avoid distortion. The basis comes from the following styling example.

import QtQuick
import QtQuick.Controls

Window {
    id: root

    color: "white"
    width: 640
    height: 480
    visible: true

    ProgressBar {
        id: control
        anchors.centerIn: parent
        value: 0.5
        padding: 2

        background: Rectangle {
            implicitWidth: 200
            implicitHeight: 40
            color: "#e6e6e6"
            radius: 3
        }

        contentItem: Item {
            id: content
            implicitWidth: 200
            implicitHeight: 40

            Item {
                width: control.visualPosition * parent.width
                height: parent.height
                clip: true

                Image {
                    width: content.width
                    height: parent.height
                    fillMode: Image.PreserveAspectCrop
                    source: "https://picsum.photos/300/200"
                }
            }
        }
    }

    Timer {
        running: true
        repeat: true
        interval: 500
        onTriggered: control.value = (control.value   0.02) % 1.0
    }
}

CodePudding user response:

I noticed the ProgressBar definition you're using appears to be from QtQuick 1? You will find support for QtQuick 1 to be waning. I base the following on the QtQuick 2 implementation of the ProgressBar.

To cater for your requirements, I decided to reconstruct a ProgressBar by using Rectangle and Image in a creative manner.

First, let's look at the Image and how you're going to fit it into a Rectangle progress bar. I gave it some thought and, most likely your source image is square? If that's the case, consider the following code:

Rectangle {
    width: 200
    height: 50
    Image {
        anchors.fill: parent
        source: backgroundImage
        sourceSize: Qt.size(height, height)
        fillMode: Image.Tile 
    }
}

In the above, we have the following assumptions:

  1. The source backgroundImage is square, NxN pixels
  2. The progress bar is rectangle, e.g. 200x50
  3. We want to tile the background image in 50x50 tiles

To do that, we make use of sourceSize: Qt.size(50,50) which will downsample your source image to fir the progressbar based on it's height. The fillMode: Image.Tile which will cause the background image to be tiled neatly.

Here's a complete working example of the above implemented as MyProgressBar with an animation showing the progress moving from 0.0 to 1.0.

import QtQuick
import QtQuick.Controls
Page {
    background: Rectangle { color: "#848895" }
    MyProgressBar {
        id: pb
        anchors.centerIn: parent
        width: 300
        height: 50
        from: 0.0
        to: 1.0
        backgroundImage: "https://www.arcgis.com/sharing/rest/content/items/185841a46dd1440d87e6fbf464af7849/data"
    }
    NumberAnimation {
        target: pb
        property: "value"
        loops: Animation.Infinite
        running: true
        from: 0; to: 1.0
        duration: 10000
    }
}

// MyProgressBar.qml
import QtQuick
import QtQuick.Controls
Rectangle {
    width: 200
    height: 50
    property real from: 0.0
    property real to: 1.0
    property real value: 0.0
    property url backgroundImage
    border.color: "grey"
    Image {
        anchors.fill: parent
        source: backgroundImage
        sourceSize: Qt.size(height, height)
        fillMode: Image.Tile 
    }
    Rectangle {
        anchors.right: parent.right
        width: (to - value) / (to - from) * parent.width
        height: parent.height
        color: "steelblue"
        border.color: "grey"
    }
}

You can Try it Online!

  • Related