QML 自定义Calendar控件

日历控件是基于 Qt5.x 以上,导入 QtQuick.Controls.1.2 即可使用。在看我这篇博客之前,最好选择 Calendar 按 F1 查看 Qt Creator 的帮助文档,或者查看 Calendar 的官方文档所在网页,因为我这篇博客也基本上参考的官方文档,只是在其基础上写了个 Demo。

一、展示

x先看下效果:

二、属性、信号和方法

2.1 属性

日历控件使用 style:CalendarStyle 设置样式,常用属性如下:

  • gridVisible : bool

    网格是否可见。默认为真

  • gridColor : color

    网格线的颜色

  • background : Component

    日历的背景。日历的隐式尺寸的计算基于背景的隐式尺寸

  • navigationBar : Component

    导航条的样式。在日历的顶部,包含下个月,上个月和选择的日期 Label

  • dayDelegate : Component

    主要设置日期的样式

  • dayOfWeekDelegate : Component

    每周的样式。周天的高度基于隐式的显示框的高度计算

  • weekNumberDelegate : Component

    周数的样式。显示框的隐式宽用来计算周数的宽

下面的数据会提供给 dayDelegate 的组件:

styleData.date 样式中的日期,属性为date
styleData.selected 如果为真,日期被选择 属性为bool
styleData.index 这个delegate的索引 属性为int
styleData.valid 日期有效则为真,属性bool
styleData.today 日期为今天,为真。属性bool
styleData.visibleMonth 日期在今月,为真,属性bool
styleData.hovered 鼠标悬停在这个单元,为真。即使日期无效。属性bool
styleData.pressed 鼠标在单元按下,为真,即使日期无效。属性bool

2.2 信号

常用信号如下所示,这里不做过多介绍,看信号名就一目了然,实在不行查看官方文档:

// Signals
clicked(date date)
doubleClicked(date date)
hovered(date date)
pressed(date date)
released(date date)

2.3 方法

常用方法(函数)如下所示,这里也不做过多介绍,详情查看官方文档:

// Methods 
showNextMonth()
showNextYear()
showPreviousMonth()
showPreviousYear()

三、代码

main.qml:

import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4

Rectangle {
    visible: true
     400
    height: 440

    // 定时器:用于延时
    Timer {
        id: timer
    }

    // 计算两个时间之间的天数
    function getDays() {
        var curDate = new Date();   // 当前日期
        var endDate = calendar.selectedDate -12*60*60*1000 // 结束日期
        var day = (endDate - curDate)/1000/60/60/24
        if(day > -1.0)
            return parseInt(day+1);
        else
            return parseInt(day);
    }

    // 延时函数
    function delay(delayTime, cb) {
        timer.interval = delayTime;
        timer.repeat = false;
        timer.triggered.connect(cb);
        timer.start();
    }

    // 获得剩余天数(curDate 到 endDate)
    function getRemainDay() {
        var remainDay = 10
        return remainDay
    }

    // MouseArea的层级在"其它所有控件"之下(因为写在"其它所有控件"的后面,又是同级的)
    MouseArea{
        anchors.fill: parent
        onPressed: parent.forceActiveFocus() // 强制让窗口获得焦点
    }

    TextField {
        id: textAreaEnd
         320
        height: 40
        placeholderText: "请选择日期"
        readOnly: true // 只读
        font.pointSize: 18
        anchors.top: parent.top
        anchors.topMargin: 30
        anchors.horizontalCenter: parent.horizontalCenter

        // 检测焦点是否在文本输入框中,在则弹出"日历"
        onFocusChanged: {
            if (activeFocus)
                calendar.visible = true
            else
                calendar.visible = false
        }

        // 避免选择日期后"日历"隐藏,焦点此时还在"文本框"上,无法进入"焦点改变事件"显示"日历"的情况
        MouseArea {
            anchors.fill: parent
            onClicked: {
                calendar.visible = true
                parent.forceActiveFocus()
            }
        }
    }

    // 日历控件
    Calendar {
        id: calendar
        anchors.top: textAreaEnd.bottom
        anchors.left: textAreaEnd.left
         textAreaEnd.width
        height: 320
        visible: false
        minimumDate: new Date()

        // 日历样式
        style: CalendarStyle {
            gridVisible: false // 网格不可见


            // 设置日期的样式
            dayDelegate: Rectangle {

                // 日期是否为今天
                property bool bIsToday: styleData.date.toLocaleString(Qt.locale("de_DE"), "yyyy-MM-dd") ===
                                        (new Date()).toLocaleString(Qt.locale("de_DE"), "yyyy-MM-dd")

                gradient: Gradient {
                    GradientStop {
                        position: 0.00
                        color: styleData.selected && styleData.date >= new Date() ? "SlateGray" : "white"
                    }
                }

                Label {
                    id: labDay
                    text: styleData.date.getDate()
                    font.family: "Microsoft YaHei"
                    font.pixelSize: 16
                    anchors.centerIn: parent
                    color: (styleData.date > new Date() && styleData.selected) ? "white" :
                           ((styleData.date > new Date() && styleData.visibleMonth)
                           ? (bIsToday ? "blue" : "black") : "Silver")
                }
            }
        }

        // 选择结束日期之后,隐藏日历
        onClicked: {
            textAreaEnd.text = Qt.formatDateTime(calendar.selectedDate, "yyyy-MM-dd")            

            // 延时一会儿才隐藏日历(第二个参数为"函数")
            delay(200, function() {calendar.visible = false})
        }
    }
}

实现功能:

  • 设置日历控件的今天前的日期为"不可选状态";

  • 点击 TextField 弹出日历,点击窗口空白区域隐藏日历;

  • 选择日期之后,延时隐藏日历;

  • 计算今天与选择日期之间的天数。

四、代码下载

GitHub 下载链接:https://github.com/confidentFeng/QML_Demo/tree/master/CalendarUse


参考:

QML类型说明-CalendarStyle-翻译

Qml日历

QML2.0下的丰富的控件之日历

QML QtQuick.Controls 1 Calendar日历样式自定义


原文地址:https://www.cnblogs.com/linuxAndMcu/p/13632176.html