Using QTimer for displaying timer - c++

I created a class called aTimer which inherits from QTimer. I want to be able to store the time elapsed into a variable called TimeElapsed of type int. I then want to have the timer automatically started when the main window opens and for it to display the time elapsed therein.
I think I'm using the wrong timer, and I am quite confused as to which tools to be using within Qt because there are different ways of handling time. Suffice it to say that I want a stop-watch kind of module that allows me to start and stop time manually without a cap (or an interval with the case of Timer). How shall I proceed? So far, attempts to use QTimer are fruitless.

You do not really need a derived class for this task. I'd probably use a QTimer and a QElapsedTimer.
Create them in your main window constructor and set the QTimers interval according to how often the time should be updated. Also connect its timeout() signal to a function updating the displayed value. In this function you can get the elapsed time from the QElapsedTimer and update the display.
// *.h
QTimer* timer;
QElapsedTimer *eltimer;
// *.cpp
constructor(){
this->timer = new QTimer(this);
this->timer->setInterval(1000);
connect(this->timer, SIGNAL(timeout()), this, SLOT(update_ui()));
this->timer->start();
this->eltimer = new QElapsedTimer(this);
this->eltimer->start();
}
SLOT update_ui(){
qint64 msecs_elapsed = this->eltimer->elapsed();
// Insert value into ui object
}
Of course you can create some buttons to start() and stop() the QTimer

Related

QT update Linedit at runtime

I am trying to update the text on my linedit every time I get a frame, but my program crash. I tried doing the same with a loop, but the window shows only after the loop has finished. setH() is my slot, in Debug mode it run perfectly, the problem is when trying to update the text in LineEdit while the programm is running(the mainwindow is on the screen) . Thank you
void MainWindow::updatehand(){
if (controller.isConnected()){
int hc =frame.hands().count();
QString hndc= QString::number(hc);
emit hChanged(hndc);
}
void MainWindow::setH(const QString hndc){
handsRead->setText(hndc);
updatehand();
}
It is the reason for the crash:
connect(this, SIGNAL(hChanged(const QString)), this, SLOT(setH(const QString)));
Such connection is acutally a direct function call. The function setH() is called in place of emit hChanged(hndc);. Then the function updatehand() is called from setH().
It is an infinite loop with the stack overflow crash.
If you want to call updatehand() 60 times per seconds it is possible to called using QTimer, for example with QTimer statics memember:
void MainWindow::setH(const QString hndc){
handsRead->setText(hndc);
QTimer::singleShot(1000 / 60, this, SLOT(updatehand()));
}
Here updatehand() is also a slot.
In that case the even loop continues to dispatch UI messages after return from setH().
Approximately after 16 ms the timer will call updatehand().
The above solution technically breaks the infinite cross-refernce loop. However, it can be done better. There is a risk that setH() will be triggered many times from the external caller. In that case many timers will be activated.
It looks that you need just one QTimer instance to call periodiacally updatehand() independently of setH(). So, updatehand() can be pooled with given period to updated data. It can call setH() directly, the setH() function only sets the QLineEdit text:
void MainWindow::setH(const QString hndc){
handsRead->setText(hndc);
}

Qt : how to automate looped slider movement in the background?

What's the most straightforward approach to have a slider move in a loop at a given speed when a button is pressed? I'm guessing it involves forking a thread that sends the appropriate signals periodically to the slider. Is there an canonical approach example for doing this?
I would suggest to use QPropertyAnimation to do the job. just set the start value, the end value and the curve you want the value to change
QPropertyAnimation *animation = new QPropertyAnimation(slider,"sliderPosition");
//set the duration (how long the animation should run - will change value faster when shorter)
animation->setDuration(1000);
//set the start value - in this case check if value in range of the slider
animation->setStartValue(slider->minimum());
//same as start value
animation->setEndValue(slider->maximum());
//easingCurve defines if it goes straight or bouncing n stuff
animation->setEasingCurve(QEasingCurve::OutCubic);
// as coyote mentioned, you can loop the animation as well (credit him as well ;))
// -1 defines to run forever
animation->setLoopCount(loopCount)
animation->start();
This would just be a matter of updating the slider's position on a timer. So, create a timer and on each update, call QSlider::setValue.
When the value is at maximum, set it back to the minimum and continue.
QSlider* pSlider = new QSlider;
QButton * pButton = new QButton("Go");
QTimer* pTimer = nullptr; // C++ 11 nullptr
// On button click, start a timer
connect(pButton, &QButton::clicked(), [=](){
// exit if already running
if(pTimer)
return;
pTimer = new QTimer;
connect(pTimer, &QTimer::timeout, [=](){
if(pSlider->value()+1 > pSlider->maximum())
pSlider->setValue(pSlider->minimum());
else
pSlider->setValue(++pSlider->value());
});
pTimer->start(1000); // update every second
});
You can use QTimer. Minimal example:
QSlider *sl = new QSlider;
QTimer *ttt = new QTimer;
sl->setValue(0);
connect(ttt,&QTimer::timeout,[=]() {
sl->setValue(sl->value() + 5);
});
sl->show();
ttt->start(500);
I used here C++11 (CONFIG += c++11 to .pro file) and new syntax of signals and slots, but of course you can use old syntax if you want.
There's no canonical approach to my knowledge.
The timers are given in the other answers, but you can also use the animation framework, and adjust the speed by adjusting the duration of the animation.
You can set the loopcount to how many times you want the animation to run, for example 1000000 to make it run a long time.

Qt - Creating a notification at a certain time (PC)

For school I have to create a calendar program for the PC with Qt,
this calendar also has to give notifications a certain time before some scheduled appointment starts.
But i have trouble finding out how I exactly can create this notifications without using a while loop (which will stop my program), I would be really thankfully if someone can help me a bit with that certain part of my project.
Thank you,
Dennis
You can create a QTimer instance with interval set to 1 second. Then connect to QTimer::timeout() signal and in the slot you can check whether there is any appointment approaching, something like that:
void YourClass::slotNameForTimeoutSignal()
{
static const int fifteenMinutes = 15 * 60;
foreach (const Appointment& app : allAppoitments)
{
if ((app.getStartUnixTime() - QDateTime::currentDateTime().toTime_t()) <= fifteenMinutes)
{
notifyAboutTheAppointment(app); // implement this method to display notification
}
}
}
This code assumes you have some kind of Appointment class/structure which holds unixtime when the appoitment starts. The timer setup is easy. Somewhere in your application initialization create a timer (which should be a member field in your class), set it up and run:
YourClass::YourClass()
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(slotNameForTimeoutSignal()));
timer->setInterval(1000);
timer->setSingheShot(false);
timer->start();
}
If you didn't know it yet, the unixtime is a time format, which is a integer number - a number of seconds that passed since the begining of 1970. Here's more details: http://en.wikipedia.org/wiki/Unix_time
Also if you're not familar with signals/slots in Qt, you should really read first about those in Qt documentation.
You can subclass QCalendarWidget to create your GUI i.e. the user can select the date when he wants the appointment. Use the QTimer to trigger the SIGNAL at your precise appointment time.
Now you can get the current date and time using QDateTime.
1. Check if the appointment is on the same date as current.
2. If yes jump to step no 4.
3. Set a timer using QTimer to emit a SIGNAL after 24 hours and connect this SIGNAL to your custom SLOT which will check if the current date is same as appointment date. Continue this step until your current date is same as appointment date.
4. Calculate the time difference between your appointment and current time and set this difference to a QTimer which will emit a SIGNAL at the required time.
5. This emitted SIGNAL would be connected a SLOT in which you are doing whatever is needed when the appointment is reached
I hope this helps you get in track.
Giving code would be like solving your homework which I don't want to do.

How to implement a game-loop with C++ and QtQuick

I'm developing a game with QtQuick 2 (Qt5.2) QML and C++. I want most of the game-logic in C++ (I don't want to do it with JS), and I'm trying to use QStateMachines for a lot of the logic.
Now my question is, how do I implement a proper game-loop in that scenario?
The game has for example objects that are moving from and to certain waypoints on the screen, so I think I can't do everything state/event-based. At some point I need to say "my object should move 10 pixels in direction x every second". So for example when my object is in its state "moving", it should move by a certain amount every second and then of course check for some conditions if it has to switch the state (e.g. to "attacking").
Now all the demos in the Qt-examples and on the web seem to be either fully event-based (e.g. four-in-a-row-wins-like) or written in JavaScript. So I am a bit lost here.
One idea I could find was to create a QTimer with a timer of e.g. 30ms and connect that QTimer's timeout() signal to an advance() slot of every moving object, and start that timer before 'return app.exec();'. Like this:
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
timer.start(1000 / 33);
return app.exec();
and then each object (e.g. the Mouse) has a
void Mouse::advance(int step)
However, this requires a QGraphicsScene and I'm not sure how well that goes with a QtQuick/QML project on Android/iOS.
Is that a good solution? Or is my view of the problem somehow wrong and I don't need a game loop to accomplish my goal?
The solution shouldn't use any desktop-only stuff from Qt, i.e. it should work on Android, iOS and desktops.
That's the way to go: QTimer. Here you find some detailed example on it:
A typical loop for game in Qt:
int main(int argc, char* argv[]) {
// init stuff
while(game.isRunning()) {
a.processEvents(); //(a is a QApplication created during the init, should use a better name i guess)
QTime currentTime= QTime::currentTime();
int timeSinceLastUpdate = lastUpdate.msecsTo(currentTime);
while(timeSinceLastUpdate>updateTimeStep){
game.update();
timeSinceLastUpdate-=updateTimeStep;
lastUpdate=lastUpdateaddMSecs(updateTimeStep);
}
renderer.setInterpolateFraction(static_cast<float>(timeSinceLastUpdate)/static_cast<float>updateTimeStep);
renderer.renderGameObjects();
renderer.renderGUI();
renderer.swap();
}
a.exit();
return 0;
}
Source: Game loop in Qt
Making a Simple Game Loop with QTimer
Qt as a game engine
That's should be enough info for you to get started.
Usual game loop of simple game can look like this (not sure if I understand you correctly though).
Each class that represents game object have 2 public methods: update(); and render();
On each call of QTimer object you iterate over all game objects and call their update method. After it you repeat the same for render method();
In update methods each object decides what to do on game map (move/shot/stand/...) and changes its coordinates/properties. In render methods each object just draws itself on display.

QTimer - Repetitive Timer

I'm trying to have an QTimer object count in intervals, continuously to call a function. I followed an example and I have set the intervals but it doesn't appear to start counting ever again.
This is the piece of code I'm working with
QTimer *timer = new QTimer(this);
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(MyFunction()));
timer->start();
Is your main loop stil running?
Does the object you reference with "this" is stil existent?
Could you check if the timer is set to single shot?
sorry didn't have the function set to a slot in the header file that was the problem
private slot:
void MyFunction();