1

Can I change the return type of a slot (such as class type or str or int)? And if that is possible, can I return two value like a normal function (such as (bool, str) or (int, str))?

Code:

class SignalSlotTest(QObject):

    get_str = QtCore.Signal(str)
    get_bool_and_str = QtCore.Signal(str)

    def __init__(self):
        super().__init__()

    def start(self):
        msg = self.get_str.emit('start1')
        print(f"start1 return : {msg}")
        (is_valid, msg) = self.get_bool_and_str.emit('start2')
        print(is_valid, msg)


class MainTest(QObject):

    @QtCore.Slot(str, result = str)         #   question 1
    def get_str_func(msg):
        return ""
    
    @QtCore.Slot(str, result=(bool, str))   #   question 2
    def get_bool_and_str_func(msg, msg2):
        return (False,"return_message")

if  __name__ == "__main__":
    main_test = MainTest()
    signal_slot_test = SignalSlotTest()
    signal_slot_test.get_str.connect(main_test.get_str_func)
    signal_slot_test.get_bool_and_str.connect(get_bool_and_str_func)
    signal_slot_test.start()

When I tested the first question, return type is 'bool' type. (It prints True).

And when I tested the second question, an error occurs:

TypeError: 'bool' object is not iterable

I don't know if my method is wrong...

ekhumoro
  • 115,249
  • 20
  • 229
  • 336

1 Answers1

2

In PyQt and PySide, emit() will never return the return-value of any connected slot. PyQt always returns None, whilst PySide always returns True. (I don't exactly know why PySide returns this value, or whether it could ever return False, as it doesn't seem to be documented anywhere).

The signal-slot mechanism provides loosely-coupled notfications between unrelated objects. Signals are broadcast entirely passively. It does not matter whether they are connected to one slot, a dozen slots, or no slots at all. The slots simply react to the signals without needing to know anything about the object that emitted them. Likewise, the behaviour of the slots is irrelevant to the signals that are connected to them.

As for Qt itself, the docs state that:

Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void).

However, there are several questions on SO that prove that this is not entirely true. For example:

And indeed, when I tested the example given in this answer, I found it still works as expected with the latest versions of both Qt5 and Qt6. However, this kind of hackery has never been possible in PyQt/PySide. Presumably, this is simply because there's no obvious use-case for it (i.e. nothing that can't be achieved by other means).

As for slots: of course it is possible to declare them to have any kind of return value in PyQt, PySide and also Qt itself. Slots aren't only made for connections to signals. They can also be invoked directly, or by the meta object system, so there's no reason to limit their return values in any way.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thanks for your detail. And thank you for correcting the question. I tried to put the code in the code block, but I couldn't upload it neatly because the declared class line didn't work well(put in the code block) like past my question. How did you modified and put in the code block? – seonguk.jeon Sep 16 '22 at 04:38
  • @seonguk.jeon You can do code blocks in two ways: (1) indent the whole block; (2) put the block inside triple backticks (see: [syntax highlighting for code](https://stackoverflow.com/editing-help#syntax-highlighting)). – ekhumoro Sep 16 '22 at 10:57