Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QTimer::singleShot() looks for the specified slot in the given object's parent class, not the object itself

I am fairly new to Qt. I have done some simple modifications to an existing Qt application, but I haven't created any from scratch yet.
I also don't have really much experience with certain aspects of C++ in general (class inheritance etc).

I have created a new Code::Blocks Qt4-based project and modified the template a bit. I have added two files.
Right now the project contains three files: main.cpp, app.h and app.cpp.
This is the content of main.cpp:

#include <QTimer>

#include "app.h"

int main(int argc, char* argv[]) {
    TestApp app(argc, argv);

    QTimer::singleShot(1000, &app, SLOT(timeout()));

    return app.exec();
}

This is what app.h looks like:

#ifndef APP_H_INCLUDED
#define APP_H_INCLUDED

#include <QApplication>

class TestApp: public QApplication {
    public:
    TestApp(int &argc, char **argv);
    public slots:
    void timeout();
};

#endif

And this is app.cpp:

#include "app.h"

#include <QDebug>

TestApp::TestApp(int &argc, char **argv): QApplication(argc, argv) {
}

void TestApp::timeout() {
    qDebug() << "timeout called";
}

I expected the program to print "timeout called" one second after startup. Unfortunately, this doesn't work. When QTimer::singleShot() is called, the console says:

Object::connect: No such slot QApplication::timeout() in [path to the main.cpp file]
Object::connect:  (receiver name: 'QtTests')

I have no idea how to deal with this. Thank you in advance.

like image 356
rhino Avatar asked Dec 17 '11 12:12

rhino


People also ask

What is QTimer singleShot?

[static] void QTimer::singleShot(int msec, const QObject *receiver, const char *member) This static function calls a slot after a given time interval. It is very convenient to use this function because you do not need to bother with a timerEvent or create a local QTimer object.

How accurate is QTimer?

From QTimer documentaion: The accuracy of timers depends on the underlying operating system and hardware. Most platforms support a resolution of 1 millisecond, though the accuracy of the timer will not equal this resolution in many real-world situations. The accuracy also depends on the timer type.

How do I restart QTimer?

To stop call QTimer::stop . To restart just call QTimer::start .

What is QObject :: connect?

To connect the signal to the slot, we use QObject::connect(). There are several ways to connect signal and slots. The first is to use function pointers: connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed); There are several advantages to using QObject::connect() with function pointers.


2 Answers

You're simply missing the Q_OBJECT macro in your TestApp class:

class TestApp: public QApplication {
    Q_OBJECT

    public:
    ...

This is necessary for the whole signal/slot infrastructure to work (and deriving from a class that has this macro is not sufficient).

(Make sure you do a full, clean build after that change - and if you don't use qmake or some other Qt-aware build system, you'll need to run moc yourself.)

For reference, see the QObject docs:

Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the Meta Object Compiler on the source file. We strongly recommend the use of this macro in all subclasses of QObject regardless of whether or not they actually use signals, slots and properties, since failure to do so may lead certain functions to exhibit strange behavior.

like image 80
Mat Avatar answered Sep 29 '22 03:09

Mat


You need to create a moc file, which is created with qmake if you put Q_OBJECT macro in your class.

So, to fix your example, you need your class changed to this :

class TestApp: public QApplication {
    Q_OBJECT
    public:
    TestApp(int &argc, char **argv);
    public slots:
    void timeout();
};
like image 38
BЈовић Avatar answered Sep 29 '22 03:09

BЈовић