Reputation: 100
I'm using Qt 5.7 trying to use a timer with timeout event in a class named MyClass. I created a public variable of this class in mainwindow.h. I put the timer's slot connect in the constructor of MyClass, and have a function in MyClass to start the timer. But when I execute the function, the timer slot doesn't work. I have no error in building, but I get the comment below on the application window at run time: QObject::connect: No such slot QObject::on_timeout()
Here is my code:
The mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "myclass.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MyClass mc;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
mc.TimerStart();
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
class MyClass : public QObject
{
public:
MyClass();
TimerStart();
QTimer *timer;
public slots:
on_timeout();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QTimer>
MyClass::MyClass()
{
timer = new QTimer(this);
}
MyClass::TimerStart()
{
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer->start(1000);
}
MyClass::on_timeout()
{
QMessageBox msg;
msg.setText("updated");
msg.exec();
}
Upvotes: 1
Views: 4499
Reputation: 98425
Q_OBJECT
to MyClass
,on_timeout
.on_timeout
slot) public.QTimer
.<QTimer>
twice.Here's how I'd write it:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
msg.setText(QStringLiteral("updated"));
connect(&timer, &QTimer::timeout, &msg, &QMessageBox::show);
}
void MyClass::timerStart()
{
timer.start(1000);
}
Here I demonstrate that implementation details should be private. You could of course do as above and set the msg
's text in the constructor, and connect directly to the msg
's SLOT(show())
.
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
Q_SLOT void on_timeout();
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
connect(&timer, SIGNAL(timeout()), SLOT(on_timeout()));
}
void MyClass::timerStart()
{
timer.start(1000);
}
void MyClass::on_timeout()
{
msg.setText("updated");
msg.show();
}
Upvotes: 6
Reputation: 15976
You forgot to add Q_OBJECT
in your class declaration:
class MyClass : public QObject
{
Q_OBJECT
// ...
If you're using Qt 5.7, you should use the Qt5 syntax for connect:
connect(timer, &QTimer::timeout, this, &MyClass::on_timeout);
By doing so, the connection will be evaluated at compile time instead of runtime. Moreover, you can connect a signal to functions even if they are not declared as slots (so you won't need the Q_OBJECT
identifier in the class declaration).
More info here.
Upvotes: 3