QtQuick 日期滚动控件

在用QtQuick来编写时间滚动控件有两种方式,一种是用PathView设置路径点,另一种则用用ListView。本次采用ListView来制作时间滚动控件。

ListView可以直接驱动鼠标滚轮和触屏点击,非常有效。Hightlight控件在delegate件的下面,如果delegate控件的

纯文字,那么文字会显示在Highlight控件的上面,展示出文字和选中的背景。如果delegate同样为一个不透明的控件,那

hightlight将被覆盖,不会显示,并且滚动时上下边界有弹动效果不是很协调,可以通过调整z值和透明度解决(弹动效果不

能解决).

这里用的做法便是像下面这样,在底层加一个背景控件设置颜色,delegate设置为透明文字控件,hightlight就可

以显示了,文字和背景都能显示,并且顶部和底部的弹动效果,也会消失(因为delegate为纯文字)。当动时view会在顶部和

底部多一个item,可设clip去掉。如下写了一个滚动并且在下下加了渐变设置

新建文件Spanner.qml   

import QtQuick 2.7

Item{
    id: spannerRoot
    width: 30
    height: titleText.height + viewRect.height
    property int itemCount: 3
    property int viewModel: 0
    property int viewModelBase: 0
    property int dataLength: 0
    property string title: ""
    property string currentText: view.currentItem.text
    signal movementEnded

    Text{
        id: titleText
        width: parent.width
        height: 20
        color: "white"
        text: title
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }

    Item{
        id: viewRect
        anchors.top: titleText.bottom
        width: parent.width
        height: itemCount * 30

        ListView{
            id: view
            anchors.fill: parent
            clip: true          //去除在拖动时顶部和底部多显示的一个item
            preferredHighlightBegin: highlightItem.height
            preferredHighlightEnd: 2 * highlightItem.height
            highlightRangeMode: ListView.StrictlyEnforceRange
            model: viewModel
            delegate: Text{
                width: parent.width
                height: 30
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                //设置不够位数左边用0补齐
                text: (new Array(dataLength).join('0') + (viewModelBase + index)).slice(-dataLength)
                color: "white"
            }
            highlight: Rectangle{
                color: "lightgreen"
            }
            onMovementEnded: spannerRoot.movementEnded(); //当滚动结束时将信号导出
        }
        //添加一个渐变色
        Rectangle{
            anchors.fill: parent
            gradient: Gradient {
                GradientStop {
                    position: 0.00;
                    color: "transparent";
                }
                GradientStop {
                    position: 0.329;
                    color: "red";
                }
                GradientStop {
                    position: 0.33;
                    color: "transparent";
                }
                GradientStop {
                    position: 0.67;
                    color: "transparent";
                }
                GradientStop {
                    position: 0.671;
                    color: "red";
                }
                GradientStop {
                    position: 1.00;
                    color: "transparent";
                }
            }
        }
    }
    //根据index设置ListView的当前item
    function setCurrentIndex(index){
        view.currentIndex = index;
    }
}
这样就可以生成一个滚动滚件,参数由外部设置;要生成日期滚动控件,我们需要复制三个,并做一些逻辑判断

新建文件DateEdit.qml   
import QtQuick 2.0

Item {
    width: dateEditRow.width
    height: dateEditRow.height

    property var dataLengthArray: [4,2,2]
    property var titleArray: ["年","月","日"]
    property var modelArray: [14,12,31] //显示model范围
    property var modelBaseArray: [year_base(modelArray[0]) + 1,1,1]//显示起点
    property string curDate: ""

    Row{
        id: dateEditRow
        spacing: 3
        Repeater{
            id: spannerRepeater
            model: 3
            Spanner{
                itemCount: 3                      //显示的item个数
                dataLength: dataLengthArray[index]//数据是几位,不够的用0在左边补齐
                title: titleArray[index]          //上面的标题
                viewModel: modelArray[index]      //总共可滚动的项目数
                viewModelBase: modelBaseArray[index] //从哪里开始
            }
            onItemAdded: {
                item.movementEnded.connect(autoCorrectDate); //绑定滚动结束的函数
            }
        }
    }

    Component.onCompleted: {
        //初始化显示当前日期
        var currentDate = new Date();
        spannerRepeater.itemAt(0).setCurrentIndex(modelArray[0] - 1);
        spannerRepeater.itemAt(1).setCurrentIndex(currentDate.getMonth());
        spannerRepeater.itemAt(2).setCurrentIndex(currentDate.getDate() - 1);
    }

    function year_base(modelCount){
        var curDate = new Date();
        var yearBase;

        if(modelArray && modelArray.length > 0)
            yearBase = curDate.getFullYear() - modelCount;
        else
            yearBase = curDate.getFullYear() - 10;

        return yearBase;
    }

    function autoCorrectDate(){
        var year = Number(spannerRepeater.itemAt(0).currentText);
        var month = Number(spannerRepeater.itemAt(1).currentText);
        var day = Number(spannerRepeater.itemAt(2).currentText);
        var monthType = month_type(month);
        switch (monthType){
        case 1:
            break;
        case 2:
            if(is_runnian(year)){
                if(day > 29)
                    spannerRepeater.itemAt(2).setCurrentIndex(modelArray[2] - 3); //最大31天润年2月最大29天,31-29+1=3
            }else{
                if(day > 28)
                    spannerRepeater.itemAt(2).setCurrentIndex(modelArray[2] - 4); //最大31天平年2月最大28天,31-28+1=4
            }
            break;
        case 3:
            if(day > 30){
                spannerRepeater.itemAt(2).setCurrentIndex(modelArray[2] - 2); //最大31天小月30天,31-30+1=2
            }
        }

        curDate = spannerRepeater.itemAt(0).currentText + '-' + spannerRepeater.itemAt(1).currentText + '-' + spannerRepeater.itemAt(2).currentText;
    }

    function is_runnian(year){
        var cond1 = year % 4 == 0;  //条件1:年份必须要能被4整除
        var cond2 = year % 100 != 0;  //条件2:年份不能是整百数
        var cond3 = year % 400 ==0;  //条件3:年份是400的倍数
        //当条件1和条件2同时成立时,就肯定是闰年,所以条件1和条件2之间为“与”的关系。
        //如果条件1和条件2不能同时成立,但如果条件3能成立,则仍然是闰年。所以条件3与前2项为“或”的关系。
        //所以得出判断闰年的表达式:
        var cond = cond1 && cond2 || cond3;
        if(cond) {
            return true;
        } else {
            return false;
        }
    }

    function month_type(month){
        if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
            return 1;
        else if(month == 2)
            return 2;
        else
            return 3;
    }
}

以下为效果截图

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值