简体   繁体   中英

How to stop a QTimer?

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.

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

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