简体   繁体   中英

How can QML native `date` type be updated?

QML provides a date type that appears to be freely convertible to and from both the C++ QDate class and the QML Date type . The Date type is an extension of the JS Date type .

Calling the set methods on a date property is apparently permissible, because no error (eg "method missing") is thrown:

// in a QML object declaration
property date myDate: new Date()
// in a slot somewhere in the object
date.setYear(2002)

However, the date data is not changed ; printing the date before and after calling setYear (or any other set method) causes exact same date string to be printed twice.

The QML documentation doesn't seem to say much about date type in the link provided above.

Let me explain to you what is wrong with the commented following exemple:

class.hpp

#ifndef CLASS_HPP
#define CLASS_HPP

#include <QObject>
#include <QDateTime>

class DateCpp : public QObject
{
    Q_OBJECT
    public:
        DateCpp();

    protected:
        // QML dates are QDateTime in C++, not QDate.
        Q_PROPERTY(QDateTime fooDate
                   READ getDate
                   WRITE setDate
                   NOTIFY fooDateChanged)
        QDateTime date;
        QDateTime getDate() const;
        void setDate(const QDateTime & d);

    signals:
        void dateChanged();
};

#endif

class.cpp

#include "class.hpp"

DateCpp::DateCpp() : QObject(), date() {}

QDateTime DateCpp::getDate() const
{
    return this->date;
}

void DateCpp::setDate(const QDateTime & newDate)
{
    this->date = newDate;

    /*
     * You have to tell QML that the property value has changed.
     * For this, use the NOTIFY signal of the property. If you do not emit it,
     * the property will not by updated on the QML side.
     */
    emit fooDateChanged();
}

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "class.hpp"

int main(int argc, char ** argv)
{
    QApplication a(argc, argv);

    // Do not forget to declare your object to QML. ;-)
    qmlRegisterType<DateCpp>("Foobar", 3, 14, "DateQML");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return a.exec();
}

main.qml

import QtQuick 2.6
import Foobar 3.14

Rectangle {
    id: rect

    // A QML date (treated as a QDateTime by the engine).
    property date rectDate

    /*
     * Binded to myDate.fooDate, but variables are at different memory spaces.
     * Will be changed together nontheless.
     */
    property date rd2: myDate.fooDate

    /*
     * Just like rd2 but it is the same object in memory, a kind of pointer
     * on DateCpp::date.
     */
    property alias rd3: myDate.fooDate

    // No "=" but ":" for property declarations.
    property date aDateProp: Date.now()

    DateQML {
        id: myDate

        // It is a kind of slot connected to the fooDate Q_PROPERTY's NOTIFY signal.
        onFooDateChanged: {
            console.log("The foodate is: " + myDate.fooDate);

            // Will trigger a signal and "onRectDateChanged" will be executed.
            rect.rectDate = myDate.fooDate;
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            /*
             * It is JavaScript. "date d" is consequently wrong here.
             * d will be a QML date (treated as a QDateTime by the engine).
             */
            var d = Date.now();
            d.setYear(2002);

            // Calls the fooDate Q_PROPERTY's WRITE method, i.e. DateCpp::setDate();.
            myDate.fooDate = d;

            /*
             * If DateCpp::setDate(); is not called here, you can still copy 
             * the property to modify what you want:
             *
             * var d2 = myDate.fooDate;
             * d2.setYear(2025);
             * myDate.fooDate = d2;
             */
            myDate.fooDate.setYear(2025);
        }
    }

    onRectDateChanged: {
        console.log("The QML property has changed: " + rect.rectDate);
    }
}

TL;DR:

  • You are dealing with QDateTime s.
  • Use the NOTIFY signal to tell the system that the value has changed.
  • No date d to declare dates in JavaScript.
  • There are not any " = " in QML properties declaration but " : ".

It appears (and air-dex's answer seems to confirm) that the date type simply can't be directly modified in this way. This is bizarre , because there are no errors triggered by attempts to call the methods.

So the solution is to simply declare date-objects that must be modified later as var rather than date .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM