32. Signals & Slots Connection Types

32.1 Direct Connection

With Qt.DirectConnection the slot is invoked immediately when the signal is emitted. In the example we create a custom signal named custom_signal. We also create three slots, on_custom_signal_1, on_custom_signal_2 and on_custom_signal_3 and connect the signal with all three slots. We add a button to the main window and emit custom_signal when it is clicked.

The output is

1 on_button_clicked: Emitting custom signal
2 
3 First custom slot executed
4 Second custom slot executed
5 Third custom slot executed
6 
7 on_button_clicked: Returning

From the output we see that when we emit the signal in on_button_clicked the three slots are called sequentially and, only after on_custom_signal_3 completes and returns, on_button_clicked continues execution. The code execution is synchronous.

When establishing the connections we didn’t pass the optional type to the Signal.connect() method. type defaults to Qt.AutoConnection and since both the signal and the slots live in the main thread the connection becomes Qt.DirectConnection.

There is one more thing to note: The slot execution bypasses the Qt event loop. We reimplement Window.event() to print a message but it is never executed.

32.2 Queued Connection

We have the same setup as in the direct connection example: a single custom signal connected to three slots.

But now the output is

 1 on_button_clicked: Emitting custom signal
 2 on_button_clicked: Returning
 3 
 4 Queued signal (MetaCallEvent) intercepted
 5 First custom slot executed
 6 
 7 Queued signal (MetaCallEvent) intercepted
 8 Second custom slot executed
 9 
10 Queued signal (MetaCallEvent) intercepted
11 Third custom slot executed

Now each slot execution is queued in the Qt event loop. After emitting the signal on_button_clicked continues execution and returns immediately, returning control to the event loop, allowing the slots to be executed. Each slot execution is wrapped in an asynchronous method invocation via QMetaObject::invokeMethod().

All three slots are still executed in the receiver thread which happens to be the main thread.

32.3 Blocking Queued Connection

Qt.BlockingQueuedConnection behaves the same as Qt::QueuedConnection, except that the signalling thread blocks until the slot returns.

We have two worker objects: the Sender object signals the Receiver to do_work. Receiver in turn signals to the Sender that the work results are ready so that the Sender can handle_results.

In the main window we connect the signals with the slots. If we use Qt.BlockingQueuedConnection:

1 self.receiver_obj.result_ready.connect(
2     self.sender_obj.handle_results,
3     Qt.ConnectionType.BlockingQueuedConnection)

the output is

1 Receiver: Starting do_work
2 Receiver: Emitting result_ready
3 Sender: handle_results started
4 Sender: handle_results finished after delay
5 Receiver: After emit (this should delay if blocking)

The Receiver thread is blocked for five seconds after it emits results_ready and only prints the last message after Sender finished handling the results.

If we used QtQueuedConnection instead

1 self.receiver_obj.result_ready.connect(
2     self.sender_obj.handle_results)

the output is

1 Receiver: Starting do_work
2 Receiver: Emitting result_ready
3 Receiver: After emit (this should delay if blocking)
4 Sender: handle_results started
5 Sender: handle_results finished after delay

which means that do_work emits the results_ready signal and immediately continues its execution.

32.4 Unique Connection

Making your signal-slot connections unique is a good idea most of the time and Qt.UniqueConnection lets you make that explicit.

The example starts without any connections made. We make the connection on clicking the connect_btn button but we use QtUniqueConnection so the connection is established only once. All subsequent attempts to connect self.button.clicked with self.on_clicked return invalid connection objects.The label text and the console output also reflect this.

1 Connection is valid
2 Connection is invalid
3 Connection is invalid
4 Connection is invalid
5 Connection is invalid

32.5 Single-Shot Connection

While Qt.UniqueConnection makes connections unique, Qt.SingleShotConnection makes them disposable: the connection is automatically broken when the signal is emitted.

The example lets you accumulate one-shot connections by clicking the Connect signals button and their count is displayed in the label. Once you click the Click Me button all connections are broken and the on_clicked slot is executed as many times as there were connections.