[Interest] Signal/Slot connection fails, even though QMetaObject::activate is called

Sze Howe Koh szehowe.koh at gmail.com
Sat Feb 8 03:15:49 CET 2020

On Sat, 8 Feb 2020 at 06:45, Jonathan Purol <contact at folling.de> wrote:
> Hello everyone,
> I have a QMainWindow subclass called `text_editor` with a function
> `save` which looks as follows:
> ```cpp
> void text_editor::save() {
>      _textbox->document()->setModified(false);
>      _textbox->setFocus();
>      emit saved();
> }
> ```
> I now connect to that slot in another class like this:
> ```cpp
> _information_editor = new text_editor{this};
> connect(
>      _information_editor,
>      &text_editor::saved,
>      this,
>      [=]() {
>          std::cout << "hello\n";
>      }
> );
> ```

You passed `this` as the 3rd argument — this argument specifies the
"context" in which to run the lambda expression. In other words, you
are telling the lambda to run in the thread that `this` object lives

If `this` object lives in a thread that doesn't have an event loop,
the lambda will never run.

Question: Which thread does `this` live in?

> I have verified that the signal is emitted, in fact, the method
> generated by the moc:
> ```cpp
> // SIGNAL 0
> void text_editor::saved()
> {
>      QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
> }
> ```
> is definitely called (verified with gdb and some other debugging
> shenenigans).
> In addition, the connection object returned by `connect` is valid, as
> verified by its implicit bool-cast operator.
> However, "hello" is never printed.

Sanity check:
* If you write something to std::cout in main(), does it get printed?
* If you replace std::cout with qDebug(), does it get printed?

> I suspected this could be because
> `text_editor` inherits from `QMainWindow` and could have a different
> thread affinity, so I tried the following things:

Thread affinity is not affected by the inheritance tree in any way at
all. By default, the object has an affinity for the thread that
constructed it.

You can change an object's thread affinity (in other words, change the
thread that the object _lives in_) by calling QObject::moveToThread().
Note that moveToThread() must only be called in the thread that the
object currently lives in.

> 1. Move the editor to the same thread as the object which establishes
> the connection

If your text_editor is a subclass of QMainWindow, then it must always
be created in the GUI thread and it should always stay in the GUI
thread. Otherwise, Bad Things(TM) can happen.

> 2. Use a QueuedConnection

For a queued connection to work, the receiver thread must have a
running event loop.

> 3. Connect to the slot from WITHIN the text editor itself, making sure
> that we are 100% on the same slot

I don't quite understand what you mean here. Please post your connection code.

> and none of them worked.
> Just for clarification, the print of "hello" is only an example, so even
> if there was some issue with that, I would have detected it, the actual
> code is of course different.
> I'm really out of luck here, and would appreciate any help.
> Sincerely,
> Folling


More information about the Interest mailing list