snehitha
snehitha

Reputation: 91

How to create QML slider with a custom shape?

I have to create a slider with a custom shape like the one shown below (blue is the slider handle):

The red color one is groove and the blue color one is handle.

Upvotes: 0

Views: 2846

Answers (2)

rbaleksandar
rbaleksandar

Reputation: 9681

You can do this directly in QML using Canvas or in Qt C++ (example with a circular slider) and then expose the element to QML. While not a direct copy-and-paste solution check this to see a custom circular progress bar that uses arc() to draw the element. You can use line() if you want straight lines. The behaviour of the slider is also something you will have to do on your own.

You can try to inherit from Slider to try and get some (or even most) of the functionality that your element requires.

Upvotes: 0

derM
derM

Reputation: 13691

For the groove, you can use any Item to draw this shape, e.g. a Image
For the handle, you just use a Rectangle and place it according to the Slider.position, e.g. like so:

Slider {
    id: slider
    width: 400
    height: 150
    y: 200
    handle: Rectangle {
        x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
        y: Math.max(slider.topPadding, slider.availableHeight - height + slider.topPadding - ((slider.availableHeight - height) * (slider.position * 2)))
        width: 15
        height: 30
        radius: 5
        color: 'blue'
    }
}

If you have a stranger shape, just change the function for y.
You can use any function that maps a value position (range [0, 1]) to an y-value. You can use every property of the slider, to calculate an appropriate position.

Here another example, where the slider draws the sine function:

Slider {
    width: 400
    height: 150
    id: slider1
    y: 200
    handle: Rectangle {
        x: slider1.leftPadding + slider1.visualPosition * (slider1.availableWidth - width)
        y: slider1.topPadding + (slider1.availableHeight - height) / 2  + (slider1.availableHeight - height) / 2 * Math.sin(slider1.position * 10)
        width: 15
        height: 30
        radius: 5
        color: 'blue'
    }
}

And here for the fun of it: A random function. But I don't think you can draw a fitting groove to it

Slider {
    id: slider
    width: 400
    height: 150
    y: 200
    onPositionChanged: {
        var a = Math.round(Math.random() * 5) - Math.round(Math.random() * 5)
        console.log(a)
        handle.handleY = handle.y + (a)
        console.log(handle.handleY)
    }
    handle: Rectangle {
        property int handleY: slider.topPadding + slider.availableHeight / 2 - height / 2
        x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
        y: Math.max(slider.topPadding, Math.min(handleY, slider.availableHeight - height + slider.topPadding))
        width: 15
        height: 30
        radius: 5
        color: 'blue'
    }
}

Upvotes: 1

Related Questions