QML 日历:可见日期列表
QML Calendar: list of visible days
有没有办法获取当前月份视图的可见日期列表(包括 previous/next 月份的可见日期)
如果我们检查 Calendar
here 的代码,我们可以发现一个可疑的 属性 __model
。我们发现,它的 count
始终为 42 - 这是可见的天数。
问题是,在 QML 中我们无法真正访问 QAbstractItemModel
的后代,因为我们需要 QModelIndex
来获取数据,使用 int
而不是 roleNames
来识别角色 e.t.c.
所以我们需要引入一个小帮手,它为我们提供了一个 get(index)
函数,正如 ListModel
所知道的那样。作为基础,我们可以使用 QIdentityProxyModel
,我们将通过缺失的公开方法扩展它。
qmlproxymodel.h
#ifndef QMLPROXYMODEL_H
#define QMLPROXYMODEL_H
#include <QObject>
#include <QIdentityProxyModel>
#include <QMap>
class QMLProxyModel : public QIdentityProxyModel
{
Q_OBJECT
public:
QMLProxyModel(QObject* parent = nullptr);
public slots:
QMap<QString, QVariant> get(int row_index) const;
};
#endif // QMLPROXYMODEL_H
qmlproxymodel.cpp
#include "qmlproxymodel.h"
QMLProxyModel::QMLProxyModel(QObject* parent)
: QIdentityProxyModel(parent)
{
}
QMap<QString, QVariant> QMLProxyModel::get(int row_index) const
{
QMap<QString, QVariant> ret;
QModelIndex ind = index(row_index, 0);
QHash<int, QByteArray> roles = roleNames();
// for some reason the itemData-method always throw a index-out-of-range exception
for (int e : roles.keys()) {
ret.insert(roles.value(e), data(ind, e));
}
return ret;
}
然后我们在main.cpp
中将这个新类型注册到QML
qmlRegisterType<QMLProxyModel>("QMLProxyModel", 1, 0, "QMLProxyModel");
终于在QML中使用了:
Calendar {
id: cal
anchors.fill: parent
}
QMLProxyModel {
id: pm
sourceModel: cal.__model
onDataChanged: console.log("Some Data has changed", pm.get(0).date)
}
这里我输出的是每当模型的数据发生变化时第一个显示的日期——也就是选择下个月的时候。
编写一个 JS 函数来遍历 QMLProxyModel
的所有 (42) 个元素以将内容添加到您想要的任何数据结构对您来说应该很容易。
如果有人感兴趣,我找到了一个更快的解决方法。以下代码考虑从星期一或星期日开始的一周。
我查了哪一天是一个月的第一天,得到了第一周的Monday/Sunday,然后我查了day = firstDay + X
where X goes from 0 to 42
.
function checkMonthlyCases(currentYear, currentMonth){
var firstMonthDay = new Date(currentYear,currentMonth,1,0)
var firstVisibleDay = new Date(firstMonthDay.getTime() - (((firstMonthDay.getDay() === Locale.Sunday) ? Qt.Sunday : firstMonthDay.getDay()) - 1) * 86400000 )
if( startDay == Qt.Sunday){
firstVisibleDay = new Date(firstVisibleDay.getTime() - 86400000);
}
for(var i=0; i< 42; i++){ // 42: number of visible days
var checkDay = new Date(firstVisibleDay.getTime() + i*86400000)
var count = getDayCaseCount(checkDay)
}
}
有没有办法获取当前月份视图的可见日期列表(包括 previous/next 月份的可见日期)
如果我们检查 Calendar
here 的代码,我们可以发现一个可疑的 属性 __model
。我们发现,它的 count
始终为 42 - 这是可见的天数。
问题是,在 QML 中我们无法真正访问 QAbstractItemModel
的后代,因为我们需要 QModelIndex
来获取数据,使用 int
而不是 roleNames
来识别角色 e.t.c.
所以我们需要引入一个小帮手,它为我们提供了一个 get(index)
函数,正如 ListModel
所知道的那样。作为基础,我们可以使用 QIdentityProxyModel
,我们将通过缺失的公开方法扩展它。
qmlproxymodel.h
#ifndef QMLPROXYMODEL_H
#define QMLPROXYMODEL_H
#include <QObject>
#include <QIdentityProxyModel>
#include <QMap>
class QMLProxyModel : public QIdentityProxyModel
{
Q_OBJECT
public:
QMLProxyModel(QObject* parent = nullptr);
public slots:
QMap<QString, QVariant> get(int row_index) const;
};
#endif // QMLPROXYMODEL_H
qmlproxymodel.cpp
#include "qmlproxymodel.h"
QMLProxyModel::QMLProxyModel(QObject* parent)
: QIdentityProxyModel(parent)
{
}
QMap<QString, QVariant> QMLProxyModel::get(int row_index) const
{
QMap<QString, QVariant> ret;
QModelIndex ind = index(row_index, 0);
QHash<int, QByteArray> roles = roleNames();
// for some reason the itemData-method always throw a index-out-of-range exception
for (int e : roles.keys()) {
ret.insert(roles.value(e), data(ind, e));
}
return ret;
}
然后我们在main.cpp
中将这个新类型注册到QMLqmlRegisterType<QMLProxyModel>("QMLProxyModel", 1, 0, "QMLProxyModel");
终于在QML中使用了:
Calendar {
id: cal
anchors.fill: parent
}
QMLProxyModel {
id: pm
sourceModel: cal.__model
onDataChanged: console.log("Some Data has changed", pm.get(0).date)
}
这里我输出的是每当模型的数据发生变化时第一个显示的日期——也就是选择下个月的时候。
编写一个 JS 函数来遍历 QMLProxyModel
的所有 (42) 个元素以将内容添加到您想要的任何数据结构对您来说应该很容易。
如果有人感兴趣,我找到了一个更快的解决方法。以下代码考虑从星期一或星期日开始的一周。
我查了哪一天是一个月的第一天,得到了第一周的Monday/Sunday,然后我查了day = firstDay + X
where X goes from 0 to 42
.
function checkMonthlyCases(currentYear, currentMonth){
var firstMonthDay = new Date(currentYear,currentMonth,1,0)
var firstVisibleDay = new Date(firstMonthDay.getTime() - (((firstMonthDay.getDay() === Locale.Sunday) ? Qt.Sunday : firstMonthDay.getDay()) - 1) * 86400000 )
if( startDay == Qt.Sunday){
firstVisibleDay = new Date(firstVisibleDay.getTime() - 86400000);
}
for(var i=0; i< 42; i++){ // 42: number of visible days
var checkDay = new Date(firstVisibleDay.getTime() + i*86400000)
var count = getDayCaseCount(checkDay)
}
}