qtqmlqtquick2qtquickcontrolsqtquickextras

Adding a custom border for each TumblerColumn


I have just started looking into QML and QT Quick Controls and been playing around with the Tumbler control. At the moment, I have modified the example and tried to customise it to get a feel for the controls.

So, the way it stands is as follows:

Tumbler {
        id: tumbler
        anchors.centerIn: parent

        Label {
            id: characterMetrics
            font.bold: true
            font.pixelSize: textSingleton.font.pixelSize * 1.25
            visible: false
            text: "M"
        }

// Just add the month column for simplicity
TumblerColumn {
            id: monthColumn
            width: characterMetrics.width * 3 + tumbler.delegateTextMargins
            model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
        }
}

Now I have overridden most if the default styles as follows:

style: TumblerStyle {
            id: tumblerStyle

            delegate: Item {
                implicitHeight: (tumbler.height - padding.top - padding.bottom) / tumblerStyle.visibleItemCount

                Text {
                    id: label
                    text: styleData.value
                    color: styleData.current ? "#52E16D" : "#808285"
                    font.bold: true
                    font.pixelSize: textSingleton.font.pixelSize * 1.5
                    opacity: 0.4 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
                    anchors.centerIn: parent
                }
            }

            // No frame
            property Component frame: Canvas {
                onPaint: {

                }
            }

            property Component separator: Canvas {
                implicitWidth: Math.max(10, Math.round(textSingleton.implicitHeight * 0.4))
                onPaint: {
                    // Do not draw any separator
                }
            }

            // No gradient background
            property Component background: Rectangle {
            }


            property Component foreground: Item {
                clip: true
                Rectangle {
                    id: rect
                    anchors.fill: parent
                    // Go one pixel larger than our parent so that we can hide our one pixel frame
                    // that the shadow is created from.
                    anchors.margins: -1
                    color: "transparent"
                    border.color: "black"
                    visible: false
                }

                DropShadow {
                }
            }
        }

Now what I want to do is instead of having a frame around the whole tumbler control, I just want to draw a line at the top and bottom if the TumblerColumn. So one can imagine that my Tumbler has many TumblerColumns and I just want to be able to basically be able to just draw a line at the top of the control along its width and at the bottom.

However, it seems with the TumblerStyle, I can only modify things that affect the whole Tumbler control. How is it possible to decorate a single TumblerColumn?


Solution

  • Use the columnForeground property of TumblerColumn:

    import QtQuick 2.4
    import QtQuick.Window 2.0
    import QtQuick.Controls 1.2
    import QtQuick.Controls.Styles 1.2
    import QtQuick.Extras 1.2
    
    Window {
        id: root
        width: 600
        height: 400
        visible: true
    
        Tumbler {
            id: tumbler
            anchors.centerIn: parent
    
            Label {
                id: characterMetrics
                font.bold: true
                visible: false
                text: "M"
            }
    
            // Just add the month column for simplicity
            TumblerColumn {
                id: monthColumn
                width: characterMetrics.width * 3
                model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
                columnForeground: Item {
                    Rectangle {
                        width: parent.width
                        height: 1
                        color: "#808285"
                    }
    
                    Rectangle {
                        width: parent.width
                        height: 1
                        color: "#808285"
                        anchors.bottom: parent.bottom
                    }
                }
            }
    
            style: TumblerStyle {
                id: tumblerStyle
    
                delegate: Item {
                    implicitHeight: (tumbler.height - padding.top - padding.bottom) / tumblerStyle.visibleItemCount
    
                    Text {
                        id: label
                        text: styleData.value
                        color: styleData.current ? "#52E16D" : "#808285"
                        font.bold: true
                        opacity: 0.4 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
                        anchors.centerIn: parent
                    }
                }
    
                // No frame
                property Component frame: Item {}
    
                // Do not draw any separator
                property Component separator: Item {}
    
                // No gradient background
                property Component background: Rectangle {}
    
                property Component foreground: Item {}
            }
        }
    }
    

    custom tumbler column foreground

    If you want to use the same foreground for all columns, use the columnForeground property in TumblerStyle instead.