Wei. C Wei. C - 3 months ago 17
C++ Question

QT5 won't send timeout signal

I'm new to QT5, and I'm having a very strange problem.
I want to use QTimer to read coordinate from serial device every 0.5 second, but the QTimer won't send timeout signal.

My .h:

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void test();

private:
Ui::MainWindow *ui;
};


My .cpp:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer myTimer(this);
myTimer.setInterval(500);
myTimer.setSingleShot(false);
connect(&myTimer, SIGNAL(timeout()), this, SLOT(test()));
myTimer.start();
}

void MainWindow::test() {
qDebug() << "Time out";
}

MainWindow::~MainWindow()
{
delete ui;
}


After I started the program, not a single "Time out" shows up...

I added the following codes after "myTimer.start()":

QTime t = QTime::currentTime().addMSecs(550);
while (QTime::currentTime() < t) {
qDebug() << myTimer.remainingTime();
}


And I found that after the remaining time of "myTimer" reduced to 0, it won't refill the remaining time and start once again, it remains at 0.

Q_OBJECT is already added

Anyone got an idea?

Thank you very much!

Answer

The problem is here:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QTimer myTimer(this);
    myTimer.setInterval(500);
    myTimer.setSingleShot(false);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(test()));
    myTimer.start();
}

In the constructor you declared myTimer automatically, so it will be destroyed as soon as constructor returns. This way, by the time when you expect timeout event, myTimer does not exist anymore and thus it cannot send any signals!

The solution is straightforward: myTimer should exist all the time MainWindow object lives, so declare it in the class, not in it's constructor, and allocate it dynamically:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    void test();

private:
    QTimer *myTimer; // <--- pointer declaration.
    Ui::MainWindow *ui;
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // Allocating actual QTimer object:
    myTimer = new QTimer(this);
    // Calling methods by object pointer:
    myTimer->setInterval(500);
    myTimer->setSingleShot(false);
    connect(myTimer, SIGNAL(timeout()), this, SLOT(test()));
    myTimer->start();
}

MainWindow::~MainWindow()
{
    // Don't forget to delete after usage.
    delete myTimer;
    delete ui;
}