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日历样式自定义