1

I have a class as follows:

handler.h:

#ifndef HANDLER_H
#define HANDLER_H

#include <QObject>

class handler : public QObject
{
    Q_OBJECT

public:
    explicit handler(QObject *parent = nullptr);
    ~handler();

public slots:
    void returnHandler(int input);
};

#endif // HANDLER_H

handler.cpp:

#include "handler.h"
#include "otherclass.h"

handler::handler(QObject *parent) : QObject(parent)
{

}

handler::~handler()
{

}

void handler::returnHandler(int input)
{
    otherclass *otherclassPointer = otherclass::getInstance();
    otherclassPointer->returnFunction(input);
}

As shown, this is a very simple class, which aims to receive an input and pass the input to a function in an external class ('otherclass'). In my main application ('main.cpp'), I create a QThread, and call the returnHandler slot when the QThread is started, as follows:

main.cpp:

QThread* newThread = new QThread();
handler* handlerPointer = new handler();
handlerPointer->moveToThread(newThread);
connect(newThread, SIGNAL(started()), handlerPointer, SLOT(returnHandler(someInput)));
newThread->start();

The issue I'm having is this:

  • I'm currently get the following error:

    QObject::connect: No such slot handler::returnHandler(someInput) in ../app/main.cpp:100

  • However, if I remove the int input from the handler class (both the .h and .cpp files), the SLOT() is recognized and called successfully when the QThread is started.

Why does adding an argument cause the slot to no longer be recognized?

EDIT: Following some very informative and appreciated comments/answers below, I've modified the approach as follows:

  1. Create a signal in the handler class, which matches the parameters of the returnHandler slot. E.g. void handlerSignal(int).
  2. Used the handlerSignal() SIGNAL instead of the QThread::started() signal in the connect().
  3. Emit the handlerSignal() once the QThread is started.

`

QThread* newThread = new QThread();
handler* handlerPointer = new handler();
handlerPointer->moveToThread(newThread);
connect(handlerPointer, SIGNAL(handlerSignal(int)), handlerPointer, SLOT(returnHandler(int)));
newThread->start();
emit handlerPointer->handlerSignal(someInput);

Thanks!

Vishaal Shankar
  • 1,648
  • 14
  • 26
jars121
  • 1,127
  • 2
  • 20
  • 35
  • 1
    You have to define connection slot in this way: `SLOT(returnHandler(int)`. I.e. you need to provide rather slot's signature instead. – vahancho Apr 18 '18 at 07:29
  • Be aware, though, that signatures of `started` and `returnHandler` do not match with the additional parameter... – Aconcagua Apr 18 '18 at 07:30
  • 2
    You might (if using Qt5) prefer the new syntax: `connect(thread, &QThread::started, hp, &Handler::returnHandler);`. The new syntax even allows usage of a lambda: `connect(thread, &Qthread::started, [&hp, someInput]() { /*...*/ });`. – Aconcagua Apr 18 '18 at 07:32
  • 1
    Possible duplicate of [Qt: SIGNAL, SLOT Macro declaration](https://stackoverflow.com/questions/5880763/qt-signal-slot-macro-declaration) – Joseph D. Apr 18 '18 at 07:47

2 Answers2

6

Two things:

  1. Qt expects the signal and the slot to have the same parameter types.
  2. In SLOT(), you have to provide types, and not names for the parameters.
    SLOT(returnHandler(int))
    instead of
    SLOT(returnHandler(someInput))
    Qt uses the signals and slots's names and argument list to identify them. I your case, Qt looks for a slot named 'returnHandler' and having only one parameter, from type 'someInput'.
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
NonoxX
  • 134
  • 10
  • In this case, the signal would also have to contain an int parameter type, i.e. SIGNAL(started(int))? Is my approach incorrect if I want to pass a variable (of the required type) to the slot function, rather than just the type itself? – jars121 Apr 18 '18 at 07:53
  • Yes, I think you partly misunderstood the signal - slot mechanism Qt offers. The parameters your slot will get, are the one provided when invoking the signal that activated the slot. – NonoxX Apr 18 '18 at 08:00
  • Thanks NonoxX, I now understand and have solved this issue. – jars121 Apr 18 '18 at 08:05
0

connect takes strings as the identification of the signal & slot to connect. The macros SIGNAL and SLOT stringise their arguments (using the preprocessor functionality for that). The argument to SIGNAL or SLOT must therefore be the function name, with parameter types in the parentheses. You cannot do argument binding with them.

If you need to connect to a nullary signal, you need a nullary slot.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455