Creating QML Controls From Scratch: Switch

Chris Cortopassi


A seasoned engineer with 10+ years experience, Chris has expertise in desktop and embedded systems in larger, real-time multi-threaded applications, as well as experience using Qt-based software for complex projects within the motor control, telecommunications and civil engineering industries. 

By Chris Cortopassi | Wednesday, April 19, 2017

Continuing our QML Controls from Scratch series, this time we will implement a Switch. Switch is similar to CheckBox with the exception that it has a slidable pill (implemented with a second MouseArea and drag property) and no text property. A Switch can be toggled either by tapping or dragging.

Switch.qml

import QtQuick 2.0

Rectangle { // size controlled by height
    id: root
    
// public
    property bool checked: false; // oncheckedChanged:  print('oncheckedChanged', checked)       

// private
    width: 250;  height: 50 // default size    
    border.width: 0.05 * root.height
    radius:       0.5  * root.height
    color:        checked? 'white': 'black' // background
    opacity:      enabled? 1: 0.3 // disabled state
    
    Text {
        text:  checked?    'On': 'Off'
        color: checked? 'black': 'white'
        x:    (checked? 0: pill.width) + (parent.width - pill.width - width) / 2
        font.pixelSize: 0.5 * root.height
        anchors.verticalCenter: parent.verticalCenter        
    }
    
    MouseArea { // must be beneath pill MouseArea
        anchors.fill: parent
        onPressed:    parent.opacity = 0.5 // down state
        onReleased:   parent.opacity = 1
        onCanceled:   parent.opacity = 1
        onClicked:    checked = !checked
    }
    
    Rectangle { // pill
        id: pill
        
        x: checked? root.width - pill.width: 0 // binding must not be broken with imperative x = ...
        width: root.height;  height: width // square
        border.width: parent.border.width
        radius:       parent.radius
        
        MouseArea {
            anchors.fill: parent
            
            drag {
                target:   pill
                axis:     Drag.XAxis
                minimumX: 0
                maximumX: root.width - pill.width
            }
            
            onPressed:    parent.opacity = 0.5 // down state
            onReleased: { // releasing at the end of drag
                parent.opacity = 1
                if( checked  &&  pill.x < root.width - pill.width)  checked = false // right to left
                if(!checked  &&  pill.x)                            checked = true  // left  to right
            }
            onCanceled:   parent.opacity = 1
            onClicked:  checked = !checked // clicking on pill             
        }
    }
}

test.qml

Switch {            
    checked:          true
    onCheckedChanged: print('Switch onCheckedChanged', checked)
}

Summary

I hope you were able to successfully create a Switch. Next time I'll show you how to create a Slider. The source code can be downloaded here.



Have a question or add to the conversation: Log in Register