Creating QML Controls  From Scratch: Slider

Creating QML Controls From Scratch: Slider

By Chris Cortopassi

Slider

Continuing our QML Controls from Scratch series, this time we will implement a Slider. The Slider has value, minimum, and maximum public properties. Slider is implemented with a single MouseArea that covers the entire control and utilizes drag to handle the user sliding the "pill" (the portion which the user moves ) left and right.

The background "tray" (a horizontal line, which can be tapped) is split into left and right pieces so that it doesn't show through the pill when enabled is set to false (since the pill is partially transparent in the disabled state). The only tricky parts about Slider are the equations to compute the value from pixels and pixels from the value.

Slider.qml

import QtQuick 2.0

Item {
    id: root
    
// public
    property double maximum: 10
    property double value:    0
    property double minimum:  0
    
    signal clicked(double value);  //onClicked:{root.value = value;  print('onClicked', value)}
       
// private
    width: 500;  height: 100 // default size
    opacity: enabled  &&  !mouseArea.pressed? 1: 0.3 // disabled/pressed state
    
    Repeater { // left and right trays (so tray doesn't shine through pill in disabled state)
        model: 2
        
        delegate: Rectangle {
            x:     !index?               0: pill.x + pill.width - radius
            width: !index? pill.x + radius: root.width - x;  height: 0.1 * root.height
            radius: 0.5 * height
            color: 'black'
            anchors.verticalCenter: parent.verticalCenter
        }
    }
    
    Rectangle { // pill
        id: pill
        
        x: (value - minimum) / (maximum - minimum) * (root.width - pill.width) // pixels from value
        width: parent.height;  height: width
        border.width: 0.05 * root.height
        radius: 0.5 * height
    }
    
    MouseArea {
        id: mouseArea

        anchors.fill: parent
    
        drag {
            target:   pill
            axis:     Drag.XAxis
            maximumX: root.width - pill.width
            minimumX: 0
        }
        
        onPositionChanged:  if(drag.active) setPixels(pill.x + 0.5 * pill.width) // drag pill
        onClicked:                          setPixels(mouse.x) // tap tray
    }
    
    function setPixels(pixels) {
        var value = (maximum - minimum) / (root.width - pill.width) * (pixels - pill.width / 2) + minimum // value from pixels
        clicked(Math.min(Math.max(minimum, value), maximum)) // emit
    }
}

Test.qml

import QtQuick 2.0

Slider {
    property double backend: 0
    
    maximum:  10
    value:    backend
    minimum: -10
    
    onClicked: backend = value
}

Summary

In this post, we created a Slider. Next time we'll create a ScrollBar element. The source code can be downloaded here. Be sure to check out my webinar on-demand. I walk you through all 17 QML controls with code examples.