QML 自定义控件 时间滚筒控件

QML 仿手机时间滚筒控件

效果:共3中模式  "Date" | "Time" | "DateTime"

QML 自定义控件 时间滚筒控件_第1张图片QML 自定义控件 时间滚筒控件_第2张图片

 QML 自定义控件 时间滚筒控件_第3张图片

 main.qml

    MouseArea{
        anchors.fill: parent
        onClicked: {
            dlg.exec(Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss"));
        }
    }

    DateTimeDialog{
        id: dlg
        text: "修改系统时间"
        type: "DateTime"
        onAccepted: {
            console.log(getText("yyyy-MM-dd hh:mm:ss"));
            console.log(getText("yyyy-MM-dd"));
            console.log(getText("hh:mm:ss"));
        }
    }

DateTimeDialog.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import "./" as MC

Dialog {
    id: root
    implicitHeight: 350
    implicitWidth: 600
    padding: 0
    anchors.centerIn: parent
    closePolicy: Popup.CloseOnEscape
    background: Rectangle{
        anchors.fill: parent
        color: "#696969"
    }
    modal: true

    property string text: ""
    property string type: "DateTime"

    onTypeChanged: {
        root.implicitWidth = 600;
        tYear.visible = true;
        tMonth.visible = true;
        tDay.visible = true;
        tHour.visible = true;
        tMinute.visible = true;
        tSecond.visible = true;

        if("Date" === type){
            root.implicitWidth = 420;
            tHour.visible = false;
            tMinute.visible = false;
            tSecond.visible = false;
        }

        if("Time" === type){
            root.implicitWidth = 420;
            tYear.visible = false;
            tMonth.visible = false;
            tDay.visible = false;
        }
    }

    ColumnLayout{
        anchors.fill: parent
        spacing: 0
        anchors.bottomMargin: 20

        Rectangle{
            Layout.fillWidth: true
            Layout.preferredHeight: 30
            color: "#FFFFFF"
            Text {
                anchors.fill: parent
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignLeft
                font.pixelSize: 16
                color: Qt.lighter("#000000")
                leftPadding: 10
                text: root.text
            }
        }

        Rectangle{
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.margins: 30
            radius: 6
            color: "#444444"

            RowLayout{
                anchors.fill: parent
                spacing: 0

                MC.Tumbler{
                    id: tYear
                    text: "年"
                    min: 2000
                    max: 2100
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    onCurrentChanged: recalDay()
                }

                MC.Tumbler{
                    id: tMonth
                    text: "月"
                    min: 1
                    max: 12
                    zero: 2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    onCurrentChanged: recalDay()
                }

                MC.Tumbler{
                    id: tDay
                    text: "日"
                    min: 1
                    max: 30
                    zero: 2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                }

                MC.Tumbler{
                    id: tHour
                    text: "时"
                    min: 0
                    max: 23
                    zero: 2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                }

                MC.Tumbler{
                    id: tMinute
                    text: "分"
                    min: 0
                    max: 59
                    zero: 2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                }

                MC.Tumbler{
                    id: tSecond
                    text: "秒"
                    min: 0
                    max: 59
                    zero: 2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                }
            }
        }

        RowLayout{
            Layout.preferredHeight: 28
            Layout.fillWidth: true
            spacing: 40

            Item {
                Layout.fillWidth: true
            }

            MC.Button{
                text: "保  存"
                Layout.preferredWidth: 80
                Layout.preferredHeight: 26
                backgroundDefaultColor: "white"
                contentItemTextColor: "black"
                onClicked: root.accept()
            }

            MC.Button{
                text: "取  消"
                Layout.preferredWidth: 80
                Layout.preferredHeight: 26
                backgroundDefaultColor: "white"
                contentItemTextColor: "black"
                onClicked: root.reject()
            }

            Item {
                Layout.fillWidth: true
            }
        }
    }

    function exec(value){
        var dateTime = new Date(value);
        tYear.current = dateTime.getFullYear();
        tMonth.current = dateTime.getMonth()+1;
        tDay.current = dateTime.getDate();
        tHour.current = dateTime.getHours();
        tMinute.current = dateTime.getMinutes();
        tSecond.current = dateTime.getSeconds();

        open();
    }

    //获取时间
    function getDateTime(){
        return new Date(tYear.current, tMonth.current - 1, tDay.current, tHour.current, tMinute.current, tSecond.current);
    }

    //获取时间字符 yyyy-MM-dd hh:mm:ss
    function getText(format){
        return Qt.formatDateTime(getDateTime(), format);
    }

    //重新计算 日
    function recalDay(){
        var year = tYear.current;
        var month = tMonth.current;

        var solarMonths = [1,3,5,7,8,10,12];
        var dayMax = 31;
        if(-1 === solarMonths.indexOf(month)){
            if(2 === month){
                if(0 === year%4)
                    dayMax = 29;
                else
                    dayMax = 28;
            }else
                dayMax = 30;
        }

        if(dayMax !== tDay.max)
            tDay.max = dayMax;
    }
}

Tumbler.qml

import QtQuick 2.12
import QtQuick.Layouts 1.12

Rectangle {
    id: root
    color: "transparent"

    property string text: ""
    property int min: -1
    property int max: -1
    property int current: -1
    property int zero: 0

    //获取最终结果
    function getResult(){
        return (myPathView.currentIndex + root.min)
    }

    ColumnLayout{
        anchors.fill: parent

        Text {
            visible: (0 !== text.length)
            text: root.text
            font.pixelSize: 24
            font.bold: true
            color: "#FFFFFF"
            Layout.preferredHeight: 40
            Layout.fillWidth: true
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }

        Item {
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.margins: 10

            PathView{
                id: myPathView
                anchors.fill: parent
                currentIndex:  (-1 === root.current) ? 0 : (root.current - root.min)
                onCurrentIndexChanged: { root.current = currentIndex + root.min; }
                model: (root.max - root.min + 1)

                delegate:Item{//
                    width:myPathView.width/2
                    height:myPathView.height/myPathView.pathItemCount

                    scale: PathView.iconScale!==undefined?PathView.iconScale:1
                    opacity: PathView.iconOpacity!==undefined?PathView.iconOpacity:1
                    z:PathView.iconZ!==undefined?PathView.iconZ:1
                    transform: Rotation {
                        origin.x: width/2
                        origin.y: height/2
                        axis.x: 1
                        axis.y: 0
                        axis.z: 0
                        angle: PathView.iconAngle!==undefined?PathView.iconAngle:0
                    }

                    Text{
                        id:timeText
                        anchors.centerIn: parent
                        text: String(Number(modelData) + root.min).padStart(root.zero, '0')
                        color: PathView.isCurrentItem ? "#0099ff" : Qt.lighter("#FFFFFF")
                        font.pixelSize: 30
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                    }
                }

                pathItemCount: 3
                preferredHighlightBegin: 0.5
                preferredHighlightEnd: 0.5
                highlightRangeMode: PathView.StrictlyEnforceRange

                //交互属性,支持拖动等……
                interactive: true
                //滑动速度
                maximumFlickVelocity:1000

                path :pathVertical
                Path{//------------垂直变化------------
                    id:pathVertical
                    property int height: myPathView.height
                    startX: myPathView.width/2

                    PathLine { id:line1; x: pathVertical.startX; y: pathVertical.startY; }
                    PathAttribute { name: "iconZ"; value: 1 }
                    PathAttribute { name: "iconScale"; value: 0.6 }
                    PathAttribute { name: "iconOpacity"; value: 0.3 }
                    PathAttribute { name: "iconAngle"; value: 80  }
                    PathPercent { value: 0 }

                    // start scaling up
                    PathLine { id:line2; x: line1.x; y: line1.y + pathVertical.height; }
                    PathAttribute { name: "iconZ"; value: 2 }
                    PathAttribute { name: "iconScale"; value: 0.8 }
                    PathAttribute { name: "iconOpacity"; value: 0.4 }
                    PathAttribute { name: "iconAngle"; value: 50  }
                    PathPercent { value: 1/4 }

                    // middle point
                    PathLine { x: line2.x; y: line2.y; }
                    PathAttribute { name: "iconZ"; value: 5 }
                    PathAttribute { name: "iconScale"; value: 1.0 }
                    PathAttribute { name: "iconOpacity"; value:1.0 }
                    PathAttribute { name: "iconAngle"; value: 0  }
                    PathPercent { value: 2/4}

                    // start scaling down
                    PathLine { x: line2.x; y: line2.y; }
                    PathAttribute { name: "iconZ"; value: 2 }
                    PathAttribute { name: "iconScale"; value: 0.8}
                    PathAttribute { name: "iconOpacity"; value: 0.4 }
                    PathAttribute { name: "iconAngle"; value: -50  }
                    PathPercent { value: 3/4 }

                    // last point
                    PathLine { x: line2.x; y: line2.y; }
                    PathAttribute { name: "iconZ"; value: 1 }
                    PathAttribute { name: "iconScale"; value: 0.6 }
                    PathAttribute { name: "iconOpacity"; value:0.3 }
                    PathAttribute { name: "iconAngle"; value: -80  }
                    PathPercent { value: 1}
                }

            }

            Item {
                width: parent.width
                height:myPathView.height/myPathView.pathItemCount
                anchors.centerIn: parent

                Rectangle{
                    height: 1
                    color: "#FFFFFF"
                    anchors.top: parent.top
                    anchors.left: parent.left
                    anchors.right: parent.right
                }

                Rectangle{
                    height: 1
                    color: "#FFFFFF"
                    anchors.bottom: parent.bottom
                    anchors.left: parent.left
                    anchors.right: parent.right
                }
            }
        }
    }
}

参考连接

你可能感兴趣的:(QML,学习,qt)