Reputation: 67
So I have a simple class below that uses a QTimer to add a number to the total every 1 second:
// score.h
#include <QObject>
#include <QTimer>
class Score : public QObject
{
Q_OBJECT
public:
explicit Score(QObject *parent = nullptr);
void start();
void stop();
QTimer *timer;
int getScore();
private slots:
void update();
private:
int score;
};
// score.cpp
#include "score.h"
Score::Score(QObject *parent) : QObject(parent)
{
score = 0;
timer = new QTimer(this);
}
void Score::start()
{
timer->start(1000);
}
void Score::stop()
{
timer->stop();
}
int Score::getScore()
{
return score;
}
void Score::update()
{
score += 10;
qDebug() << score;
}
// main.cpp
#include <QCoreApplication>
#include "score.h"
#include <QtDebug>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Score score{};
std::string input{""};
while(input!="1") {
std::cout << "1. to stop" << std::endl;
std::cout << "2. to start" << std::endl;
std::cin >> input;
if(input=="1") {
score.stop();
}
else if(input=="2") {
score.start();
}
}
return a.exec();
}
During the loop, if I press if my input was 2, nothing is happening. The slot doesn't seem to fire as I don't see anything that is outputting to the console. I am pretty new to QT in general so I may have done something incorrect. Another thought I had that it could be due to some threading issues. But I haven't had much experience with threading before.
Upvotes: 0
Views: 1083
Reputation: 243897
Your implementation has 2 crucial errors:
The eventloop is never started since the while loop does not allow it, and if the eventloop is not started then asynchronous elements such as QTimer, signals, etc. will not work.
Even so, the eventloop will work. You have not made the connection between the timeout signal with the updata slot.
Considering the above you have to implement the reading of stdin without using a loop and the implementation of the reading will depend on the OS, so to simplify the solution we can use the QConsole library that implements the reading of stdin through signals:
├── 3rdParty
│ └── QConsole
│ ├── Demo
│ │ ├── Demo.pro
│ │ └── main.cpp
│ ├── LICENSE
│ ├── qconsole.cpp
│ ├── qconsole.h
│ ├── qconsole.pri
│ ├── README.md
│ ├── readthread_win.cpp
│ └── readthread_win.h
├── 64746801.pro
├── main.cpp
├── score.cpp
└── score.h
*.pro
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
SOURCES += \
main.cpp \
score.cpp
HEADERS += \
score.h
include(3rdParty/QConsole/qconsole.pri)
main.cpp
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <qconsole.h>
#include "score.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Score score;
QConsole console;
QObject::connect(&console, &QConsole::readyRead, [&](){
auto data = console.read(console.bytesAvailable());
if(data == QStringLiteral("1\n")){
score.stop();
}
else if(data == QStringLiteral("2\n")){
score.start();
}
});
if(!console.open()) {
qCritical() << console.errorString();
return EXIT_FAILURE;
}
return a.exec();
}
score.h
#ifndef SCORE_H
#define SCORE_H
#include <QObject>
class QTimer;
class Score : public QObject
{
Q_OBJECT
public:
explicit Score(QObject *parent = nullptr);
void start();
void stop();
int getScore();
private slots:
void update();
private:
int score;
QTimer *timer;
};
#endif // SCORE_H
score.cpp
#include "score.h"
#include <QTimer>
#include <QDebug>
Score::Score(QObject *parent) : QObject(parent)
{
score = 0;
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Score::update);
}
void Score::start()
{
timer->start(1000);
}
void Score::stop()
{
timer->stop();
}
int Score::getScore()
{
return score;
}
void Score::update()
{
score += 10;
qDebug() << score;
}
The full example is here
Upvotes: 1