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 QtQuick.Controls 1 Calendar日曆樣式自定義