Simple counter [SOLVED]
-
Hello everyone,
How can I make a simple counter in C++ and show the numbers in qml at the same time ?
I don't know how to start with the solution.Thanks in advance.
-
[quote author="Jacques" date="1353791901"]Hello everyone,
How can I make a simple counter in C++ and show the numbers in qml at the same time ?
I don't know how to start with the solution.Thanks in advance.[/quote]
What actually do you want to do? Start counter and increment it in some period of time + display it on the QML widget?
-
Hello Tucnak
Yes. But what bothers me is the fact that I want to have the C++ value updated on the QML in realtime. And I don't know how to do that.
-
Ok this is how it can be done:
Suppose you have the following class that will be holding the counter--
@
class MyNumberHolder : public QObject
{
Q_OBJECT
Q_PROPERTY( int counter READ number WRITE setNumber NOTIFY numberUpdated)
public:
MyNumberHolder( int value = 0 );public:
int number() const;public slots:
void setNumber( int value ){
cnt = value;
emit numberUpdated(cnt);
}signals:
void numberUpdated(int value);private:
int cnt;
};
@The Q_PROPERTY defines the new variable in the Qt's meta system by setting the name of the variable (counter) and the setter/getter function through which the value will be altered/accessed. And finally the what you need the most the NOTIFY tag specifies the signal that will be fired when the variable changes.
Next step you create an instance of the above object and register it as a property in the declarative view. For instance, in the main you can write:
@
QmlApplicationViewer viewer;
MyNumberHolder numberHolder;viewer.rootContext()->setContextProperty("counterHolder", &numberHolder);
@Now you can freely go to any of your qml file and write something like this:
@
...
Text{
id: label
Connections {
target: counterHolder
onNumberUpdated: {
label.text = counterHolder.counter
}
}
}
...
@ -
Hello,
Thanks, It works. But I have another problem. I want to make a while loop so that I don't need to click more than once. How can I manage to do that ?here is the code :
@
// Counter.h#ifndef COUNTER_H
#define COUNTER_H#include <QObject>
#include <iostream>using namespace std;
class Counter : public QObject
{
Q_OBJECTQ_PROPERTY(float counter READ getCounter WRITE setCounter NOTIFY counterUpdated)
public:
explicit Counter(QObject *parent = 0);
int getCounter();
void setCounter(int);signals:
void counterUpdated(int);public slots:
void doTheStuff();private:
int m_counter;
};#endif // COUNTER_H
@@
// Counter.cpp#include "Counter.h"
Counter::Counter(QObject *parent) :
QObject(parent)
{
m_counter = 0;
}
void Counter::doTheStuff()
{
int c = 10;//while(1) <---- this is the loop { if(m_counter < 270) setCounter(m_counter + c); else setCounter(0); }
}
int Counter::getCounter()
{
return m_counter;
}void Counter::setCounter(int c)
{
cout<<"setting counter"<<endl;
if (c != m_counter)
{
m_counter = c;
emit counterUpdated(m_counter);
}
}@
#include <QApplication>
#include "Counter.h"
#include <QDeclarativeView>
#include <QDeclarativeContext>int main(int argc, char **argv)
{
QApplication app(argc, argv);QDeclarativeView *view = new QDeclarativeView(); Counter *c1 = new Counter(); QDeclarativeContext *ctxt = view->rootContext(); ctxt->setContextProperty("myCounter", c1); view->setSource(QUrl::fromLocalFile("./main.qml")); view->show(); QObject *item = (QObject *)view->rootObject(); QObject::connect((QObject *)item, SIGNAL(launchStuff()), c1, SLOT(doTheStuff())); return app.exec();
}
@
import QtQuick 1.0
Rectangle
{
signal launchStuff()color: "black" height: 300 width: 700 Image { height: 27 width: 27 x:100 y:myCounter.counter id: name source: "./godbod.png" } MouseArea { anchors.fill:parent onClicked: { launchStuff() } }
}
@ -
The best way of doing what you want is through "QTimer":http://doc.qt.digia.com/qt/qtimer.html. A timer that every one second will call your function. Thus your application will not freeze there for ever so it will be responsive.
It goes like this:
@
// Counter.h#ifndef COUNTER_H
#define COUNTER_H#include <QObject>
#include <iostream>
#include <QTimer>using namespace std;
class Counter : public QObject
{
Q_OBJECTQ_PROPERTY(float counter READ getCounter WRITE setCounter NOTIFY counterUpdated)
public:
explicit Counter(QObject *parent = 0);
int getCounter();
void setCounter(int);signals:
void counterUpdated(int);public slots:
void doTheStuff();private:
int m_counter;
int c;
QTimer timer;
};#endif // COUNTER_H
@@
//counter.cpp
Counter::Counter(QObject *parent) :
QObject(parent)
{
m_counter = 0;
c = 10;
connect(&timer, SIGNAL(timeout()), this, SLOT(doTheStuff()));
timer->start(1000); // tick every 1 second (1000ms)
}
void Counter::doTheStuff()
{
if(m_counter < 270)
setCounter(m_counter + c);
else
setCounter(0);
}int Counter::getCounter()
{
return m_counter;
}void Counter::setCounter(int c)
{
cout<<"setting counter"<<endl;
if (c != m_counter)
{
m_counter = c;
emit counterUpdated(m_counter);
}
}
@ -
Okay.
Thanks a lot. It's working as I want. In a way, I had to convert from while loop to if statements... considering the program as a loop. It's another way to see things :)