How we can connect the signals and slot with different arguments?
Asked Answered
E

5

24

In Qt, signals and slots require matching argument types:

QObject::connect: Incompatible sender/receiver arguments QLabel::linkActivated(QString) --> Button::call(int)

How can I implement a combination like this?

Erotomania answered 28/10, 2011 at 8:42 Comment(0)
H
23

A simple method is to have an intermediate slot that calls the slot that you want. e.g.

connect(src, SIGNAL(linkActivated(QString)), this, SLOT(receiveLink(QString)));

and then

void receiveLink(QString blah)
{
  int response = someFunction(blah);
  mybutton->call(response);
}

You have to define some way to interpret the string into an int.

Height answered 28/10, 2011 at 8:53 Comment(0)
G
42

From the signals slots documentation:

The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.)

This means that a signal of the form

signal(int, int, QString)

can only be connected with slots with the following signatures

slot1(int, int, QString)
slot2(int, int)
slot3(int)
slot4()

As koan suggests the best approach is to use another slot with a QString argument and then call the slot you actually want.

Granophyre answered 28/10, 2011 at 9:34 Comment(1)
a slot may have a shorter signature than the signal it receives because it can ignore extra arguments. Thanks for this useful excerpt from the documentation.Stepson
H
23

A simple method is to have an intermediate slot that calls the slot that you want. e.g.

connect(src, SIGNAL(linkActivated(QString)), this, SLOT(receiveLink(QString)));

and then

void receiveLink(QString blah)
{
  int response = someFunction(blah);
  mybutton->call(response);
}

You have to define some way to interpret the string into an int.

Height answered 28/10, 2011 at 8:53 Comment(0)
U
6

Default values for slot parameters helps very well. This allow to connect signals with different signatures to slot (vice versa to @pnezis answer):

private slots:
  void slot( int x = 10, int y = 20, QString text = QString() );

may be connected to different signals:

signal1(int, int, QString)
signal2(int, int)
signal3(int)
signal4()

Also Qt 4.8 suggest useful QSignalMapper class:

This class collects a set of parameterless signals, and re-emits them with integer, string or widget parameters corresponding to the object that sent the signal.

But only for one parameter:

QSignalMapper* mapper = new QSignalMapper(this) ;

connect(action, SIGNAL(triggered()), mapper, SLOT(map())) ;
mapper->setMapping(action, "param value") ;

connect(mapper, SIGNAL(mapped(const QString &)),
  this, SIGNAL(clicked(const QString &)));
Unclean answered 11/3, 2017 at 15:35 Comment(0)
B
1

a more modern solution would be using qOverload

struct Foo {
        void overloadedFunction(int, const QString &);
        void overloadedFunction(int, const QString &) const;
    };
    ... qConstOverload<int, const QString &>(&Foo::overloadedFunction)
    ... qNonConstOverload<int, const QString &>(&Foo::overloadedFunction)
Baldric answered 15/5, 2023 at 9:49 Comment(1)
While it's nice to see a modern API suggestion, the question is about hooking a signal requiring f(string) slot to f(int) slot. Overload resolution isn't the problem as the OP only has one function of said name but with a different parameter type.Stepson
M
0

As a complementary answer, if you don't want to write an intermediate slot, you can use the lambda expressions (of course with C++11 support) to invoke the method. However, the connector class must know the parameter types used in those particular signals and slots.

To give an example, assuming that you're trying to connect a signal with a parameter type of QString to a slot with a parameter type of char, you can do it like this;

class SignalClass{
signals:
    void testSignal(QString tString);
};

class SlotClass{
public slots:
    void testSlot(char tChar);
};

class ConnectorClass{
public:
    void connectSignalAndSlot () {
        SignalClass tSigClass;
        SlotClass tSlotClass;
        connect(&tSigClass, &SignalClass::testSignal,
                [=](QString tString) { this->metaObject()->invokeMethod(tSlotClass,"testSlot", Q_ARG(char, tString.at(0).toLatin1())) }
        );
    }
}

Kinda ugly stuff, but does the job.

  • No coupled classes
  • No intermediate connector functions
Myranda answered 3/3, 2019 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.