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
    width: 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
        width: 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
        width: 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日歷樣式自定義



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM