How to change the current time with Text



  • Hi.

    This is one of the things that it's probably not completely straightforward to do in QML. Imagine that you want to display the current time, including the seconds, in QML. If you do:

    @
    import QtQuick 1.0

    Rectangle {
    id: main
    width: 400; height: 400

    Text {
        id: foo
        font.pointSize: 24
        text: Date();
    }
    

    }
    @

    Then the "text" value is not a binding, so the time is not updated each second, of course.

    Any idea about how to solve it cleanly? I've tried using the Binding element, and qmlviewer doesn't throw any errors, but reading the docs doesn't seem the proper system anyway.

    I thought of using a timer, but doesn't seem the proper way to do it with QML.

    Any ideas?
    Thank you.



  • I can't imagine there is any other way than using a timer. If you were to try something like this on c++ you probably would end up with a timer the same way... somehow you need to decide how often you want to update the time (it is always changing...)



  • Yes, I suppose that there is no way to scape of the timer. A case like this can't be designed declaratively because the time is always changing, it it doesn't emit a signal all the time. :(

    So, it's possible to set the timer in the QML code? Or just the C++?



  • what about using javascript?



  • But how would you set it up? I mean, in C++ I would add a line in the constructor of the widget. In QML...

    Did I say that I'm quite a noob with this? :)



  • Will this work for you?

    @import QtQuick 1.0

    Rectangle {
    id: main
    width: 400; height: 400

    Text {
        id: foo
        font.pointSize: 12
      function set()
     {
            foo.text = Date();
         } 
    }
    

    Timer {
    id: textTimer
    interval: 1000
    repeat: true
    running: true
    triggeredOnStart: true
    onTriggered: {
    foo.set();
    }
    }
    }
    @



  • or that.... ;)



  • [quote author="disperso" date="1292182667"]But how would you set it up? I mean, in C++ I would add a line in the constructor of the widget. In QML...

    Did I say that I'm quite a noob with this? :)[/quote]

    QML is new so everyone is a noob. :)



  • [quote author="QtK" date="1292183966"]
    [quote author="disperso" date="1292182667"]But how would you set it up? I mean, in C++ I would add a line in the constructor of the widget. In QML...

    Did I say that I'm quite a noob with this? :)[/quote]

    QML is new so everyone is a noob. :)

    [/quote]

    Of course there are different levels of noob... :)

    On a more serious note: it is quite amazing to me how many posts we are getting about qml... I have to say that I didn't think would be such a hit!



  • QML Timer seems the proper QML way to do it to me. :)

    I'd forgotten about the Timer element myself. One of the problems with this new way of developing UIs is remember what can and can't be done in C++ vs QML.



  • Oh my, I didn't knew that a Timer existed in QML. This makes a lot of sense. Thank you!



  • I wonder if there isn't a way using an animation. I know it is overkill but it is another idea...



  • [quote author="fcrochik" date="1292185303"]I wonder if there isn't a way using an animation. I know it is overkill but it is another idea...[/quote]

    Yes, I think you can animation too. I had tried it for other values but not with date. But then yes it would be a overkill.



  • Well, an animation that triggers each second and changes the second with some eye candy is quite a stress test for the app, isn't it?

    I modified once "digiflip, frmo the graphics dojo":http://qt.gitorious.org/qt-labs/graphics-dojo/trees/03c1e210d0a54f7337dd953a10b66108c54ed827/digiflip to change each second, and it consumed quite a lot of CPU... and it's done in C++ (and only does that :P).



  • I assume you tested it on a PC or Laptop. On mobile device it might freeze.



  • Updating every second shouldn't stress the CPU since updates need to be every 16 ms to get smooth animations. Of course whether smooth animations are possible depends upon what is animating and the system animating it. I wouldn't expect updating text to be one of those cases.



  • Just another concern I have about QML application is the initial loading time it takes on Mobile Devices especially on higher ends like N97. Native Symbian applications load a lot more quickly. Hope this would be optimized in someway in future.



  • Updating something every second should definitely not affect CPU very much. Even on a mobile device. A small timer is very simple and not stressful. I have done much more wicked things in my QML code :P All done on CPU on a 400MHz device of course.

    It takes roughly 1-2 seconds to load a QML app here. Noting that the QML app includes images that are not hinted to load asynchronously. 1-2 seconds may be slower than native Symbian apps but it's still faster than apps on most platforms including iOS, Android, etc.. so I don't think there's much problem. Just need that loading process animated.



  • For eg the flowd demo you had referred to takes more time than symbian apps to load. But once loaded it works fine.



  • [quote author="xsacha" date="1292193076"]Updating something every second should definitely not affect CPU very much. Even on a mobile device. A small timer is very simple and not stressful. I have done much more wicked things in my QML code :P All done on CPU on a 400MHz device of course.
    [/quote]

    The digiflip demo that I mentioned runs smooth, but I have a widget that show the CPU usage, and if I made the numbers too big (or just not small), it goes up easily. As I said, it's c++, but honestly, it's code that I don't dare to understand deeply (I mean, the paint() stuff, the rest is easy of course).



  • If you haven't seen it already, there is a "Clocks" example in examples/declarative/toys/clocks that might also be useful to look at.

    Regards,
    Michael



  • Oh, that's true! I completely forgot that! Thanks!

    Just for the record: a Timer is used in that example.



  • [quote author="disperso" date="1292206056"]Oh, that's true! I completely forgot that! Thanks!

    Just for the record: a Timer is used in that example.[/quote]

    It seems I need to give some time to explore all the examples.



  • Another approach, just to highlight that there are different ways to do stuff, is to use C++ to make a simple clock element. This element would have properties for time and date, and update them (complete with signal) when needed. The timer would therefore move to this C++ part.

    In QML, you can then just do something like this:

    @Item {
    Clock {
    id: clock
    timeFormat: 'hh:mm:ss'
    }

    Text {
        id: timeDisplay
        text: clock.time
    }
    Text {
        id: dateDisplay
        text: clock.date
    }
    

    }
    @

    The code needed for the Clock element would not be hard at all, just a few lines of code.

    Edit:

    I just tried to implement a Clock element. It wasn't hard:

    clock.h
    @
    #ifndef CLOCK_H
    #define CLOCK_H

    #include <QDeclarativeItem>

    class QTimer;

    class Clock : public QDeclarativeItem
    {
    Q_OBJECT
    Q_PROPERTY (QString time READ time NOTIFY timeChanged)
    Q_PROPERTY (QString date READ date NOTIFY dateChanged)
    Q_PROPERTY (QString timeFormat READ timeFormat WRITE setTimeFormat NOTIFY timeFormatChanged)
    Q_PROPERTY (QString datFormate READ dateFormat WRITE setDateFormat NOTIFY dateFormatChanged)

    public:
    explicit Clock(QDeclarativeItem *parent = 0);

    QString time() const {return m_time;}
    QString date() const {return m_date;}
    QString timeFormat() const {return m_timeFormat;}
    QString dateFormat() const {return m_dateFormat;}
    
    void setTimeFormat(const QString& format);
    void setDateFormat(const QString& format);
    

    signals:
    void timeChanged();
    void dateChanged();
    void timeFormatChanged();
    void dateFormatChanged();

    public slots:

    private slots:
    void updateTimeDate();

    private:
    QString m_time;
    QString m_date;
    QString m_timeFormat;
    QString m_dateFormat;

    QTimer* m_timer;
    

    };

    #endif // CLOCK_H
    @

    clock.cpp:
    @
    #include "clock.h"
    #include <QTimer>
    #include <QDateTime>
    #include <QLocale>

    Clock::Clock(QDeclarativeItem *parent) :
    QDeclarativeItem(parent),
    m_timer(new QTimer(this))
    {
    QLocale loc;
    m_timeFormat = loc.timeFormat();
    m_dateFormat = loc.dateFormat();

    m_timer->setInterval(200);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTimeDate()));
    m_timer->start();
    updateTimeDate();
    

    }

    void Clock::setTimeFormat(const QString& format)
    {
    if (format != m_timeFormat) {
    m_timeFormat = format;
    emit timeFormatChanged();
    updateTimeDate();
    }
    }

    void Clock::setDateFormat(const QString& format)
    {
    if (format != m_dateFormat) {
    m_dateFormat = format;
    emit dateFormatChanged();
    updateTimeDate();
    }
    }

    void Clock::updateTimeDate()
    {
    QDateTime dt = QDateTime::currentDateTime();

    QString time = dt.time().toString(m_timeFormat);
    if (time != m_time) {
        m_time = time;
        emit timeChanged();
    }
    
    QString date = dt.date().toString(m_dateFormat);
    if (date != m_date) {
        m_date = date;
        emit dateChanged();
    }
    

    }
    @

    Register the class for use with QML in a line like this:
    @ qmlRegisterType<Clock>("com.test.qmlcomponent", 1, 0, "Clock");@

    In the QML, you can then import the Clock element like so:
    @import com.test.qmlcomponent 1.0@
    and use it as illustrated in my example at the top.

    If you want, you can extend the Clock class to expose the different time units seperately too. That makes it easy to use it for a clock that you display with other means than just a text, like in analog form.



  • This thread deserves becoming a wiki...

    It is very interesting to have developers trying to come up with different approaches to the same problem. Maybe we could make that a "regular" activity. Someone suggests a problem and we spend few days trying to propose different solutions.

    Anybody up for it?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.