qtqmlqtquick2qtquickcontrols

For QML, why LayoutMirroring doesn't work in Slider?


Today I tried the Slider in QtQuick.Controls, my slider is left to right, I want to set my slider as from right to left by using LayoutMirroring.enabled, at last I found I cann't inverted the slider.

Here is my little demo code, so how can we invert a slider?

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Slider{
        id:test
        value: 0.2
        width:400
        LayoutMirroring.enabled: true
    }
}

Solution

  • If you use the Slider from QtQuick.Controls 2.x - at least for me - it works like a charm. If you use the Slider from QtQuick.Controls 1.x it does not.

    From the documentation:

    Keep in mind, however, that mirroring does not affect any positioning that is defined by the Item x coordinate value, so even with mirroring enabled, it will often be necessary to apply some layout fixes to support the desired layout direction.

    The QtQuick.Controls 1.x-Slider however uses a largely coordinate based implementation and has no further precautions to support the LayoutMirroring.

    However the Sliders layout is usually symetrically, so all you need to do is to map the values like from (0,1) to (1,0). This should be a easy task to a developer.

    import QtQuick.Controls 1.3
    import QtQuick.Controls.Layouts 1.3
    import QtQuick.Controls.Private 1.3 // Needed for a mysterious value from the original, now mirrored style.
    Slider {
        y: 40
        id: sli
        width: parent.width
        minimumValue: 50
        maximumValue: 100
    
        property real mirroredValue: maximumValue - value + minimumValue
    
        // Invert style
        style: SliderStyle {
            groove: Item {
                property color fillColor: "#49d"
                anchors.verticalCenter: parent.verticalCenter
                // Whatever TextSingleton is. You need to import QtQuick.Controls.Private 1.x for it.
                implicitWidth: Math.round(TextSingleton.implicitHeight * 4.5) 
                implicitHeight: Math.max(6, Math.round(TextSingleton.implicitHeight * 0.3))
                Rectangle {
                    radius: height/2
                    anchors.fill: parent
                    border.width: 1
                    border.color: "#888"
                    gradient: Gradient {
                        GradientStop { color: "#bbb" ; position: 0 }
                        GradientStop { color: "#ccc" ; position: 0.6 }
                        GradientStop { color: "#ccc" ; position: 1 }
                    }
                }
                Item {
                    clip: true
                    x: styleData.handlePosition // let the fill-stuff start at the handle position...
                    width: parent.width - styleData.handlePosition // and end at the end of the groove.
                    height: parent.height
                    Rectangle {
                        anchors.fill: parent
                        border.color: Qt.darker(fillColor, 1.2)
                        radius: height/2
                        gradient: Gradient {
                            GradientStop {color: Qt.lighter(fillColor, 1.3)  ; position: 0}
                            GradientStop {color: fillColor ; position: 1.4}
                        }
                    }
                }
            }
        }
    }
    

    If you wan't to set the value of your slider, you need to install a bidirectional binding between mirroredValue and value.