How to pass QObject as argument from signal to slot in Qt connect
Asked Answered
G

1

9

My original code passed a QStringList from the signal to the slot and then returned a QList .
Everything worked fine but I needed to change both the QStringList and QList into 2 different subclassed QObjects. Since then I have been receiving errors like "synthesized method first required here" or it simply crashes without any error message.

I understand that qt copies all arguments passed in a queued connection and a QObject cannot be copied. So instead of returning a QObject I thought I would create both QObjects prior to emitting the signal.
Then I would pass references to each object, modify one of them in the slot function and void the return value.

Unfortunately the app still crashes no matter how I code the signal and slot functions.

How can I code the signal/slot functions and connect them to either pass both qobjects as arguments or return a qobject?

MyQObject1 obj1("a","b","c");
MyQObject2 obj2();
emit sendSignal(&obj1, &obj2);
// or
MyQObject2 obj2 = emit sendSignal(&obj1);

connect(someObj, SIGNAL(sendSignal(const QObject&)), this, SLOT(receiveSignal(const QObject&)));

The receiveSignal() function does not directly create or modify any QObject.
It has to pass the QObjects to another function first which then either modifies obj2 or creates and returns it.
Any code examples would be greatly appreciated.

Glorygloryofthesnow answered 2/8, 2013 at 19:56 Comment(0)
A
12

Usually QObject is passed by pointer, not by reference (note that QObject cannot be copied and cannot be passed by value). QObject* is registered as a meta type by default. So creating a signal and a slot with QObject* argument is enough to get them work:

private slots:
  void test_slot(QObject* object);

signals:
  void test_signal(QObject* object);

Initialization:

connect(this, SIGNAL(test_signal(QObject*)), this, SLOT(test_slot(QObject*)));

Emitting:

QObject* object = new QObject();
emit test_signal(object);

Of course the signal and the slot could be in different classes.

Anxious answered 2/8, 2013 at 20:34 Comment(7)
You don't need any metatype registration for signal/slots unless the connection is queued. And with queued connections I see ownership issues with object. Who owns it and will delete it again? The emitter? When?Germanous
QObject* is a generic metatype. It is registered by default and used by some built-in signals (e.g. destroyed). Queued connections work as well without registration. Ownership of QObject is declared by setting its parent (unless it's created on stack). Passing it by pointer generally doesn't cause ownership problem and is widely used in the Qt API. Usually there are conventions in API telling what's happening with ownership when a method (slot) is called.Anxious
Metatype: I know that, that was not my point. You said that QObject* is registered as metatype, and thus it can be used in signal/slots. It's not mandatory though; if it was, passing an argument of MyObjectSubclass* would already fail without registering MyObjectSubclass* as well.Germanous
Ownership: The problem is that the parent/child ownership won't help you with signal/slots, especially queued connections. Thus creating QObjects dynamically just to then send them via a signal isn't common practice, for good reason. The receiver can't own the object, because there can be arbitrary many receivers or none at all. In the sender they will stack up if another one is created each time test_signal() is emitted, unless the sender deletes them right away afterwards (but then the pointer would dangle when used in queued connects).Germanous
If you're using a queued connection, and the receivers might outlive the sender, then it can't delete the objects either. Thus managing the objects by shared pointer and passing QSharedPointer<MyQObjectSubclass> might be the best way out in some cases. Or just don't use signal/slots to solve the issue, it looks misapplied here.Germanous
I agree. It's hard to use this approach with queued connections. However it still might be useful with direct connection.Anxious
@Riateche - Thanks for the example. That fixed the problem. Using signals/slots is my only option since I need to communicate across threads. There will only ever be one instance of MyObject at a time since I delete it a few lines after calling "emit sendSignal(obj)". Should I call "obj->deleteLater()" as the last line in the receiveSignal() function to ensure that the object is deleted in both the sender and receiver?Glorygloryofthesnow

© 2022 - 2024 — McMap. All rights reserved.