Skip to content

Qt6 Signal Datatype Handling #426

@jakeanq

Description

@jakeanq

Another quirk for the Qt6 migration section...

If defining a signal with a list or dict datatype (potentially others too?), in Qt6 it will now convert the Python object to a C++ object, then convert it back later when calling a slot, whereas in Qt5 it will return the original object. This conversion seems to be recursive.

Some effects of this:

  • The slot receives a copy of the object, not the original.
  • If you pass a custom type that inherits from list or dict, the slot will be called with a new object of the base type.
  • Dictionary item ordering is lost.

One fix/workaround is to define the signal with object as the datatype, which will maintain the previous behaviour.

Demo script:

from Qt import QtCore, QtWidgets

class Lemur(list):
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return f"Lemur({self.value!r})"


class TestWidget(QtWidgets.QPushButton):

    test_signal = QtCore.Signal(dict)

    def __init__(self):
        super().__init__()
        self.clicked.connect(self.do_test)
        self.test_signal.connect(self.rx_test)

    def do_test(self):
        data = {"test_dictionary": 10, "lemur": Lemur("Hello")}
        print(f"tx {data=} {id(data)=} {id(data['lemur'])=}")
        self.test_signal.emit(data)

    def rx_test(self, data):
        print(f"rx {data=} {id(data)=} {id(data['lemur'])=}")


if __name__ == "__main__":
    app = QtWidgets.QApplication()
    tw = TestWidget()
    tw.show()

    app.exec_()

With PySide5 I get the exact object returned:

tx data={'test_dictionary': 10, 'lemur': Lemur('Hello')} id(data)=140451434388544 id(data['lemur'])=140451434394304
rx data={'test_dictionary': 10, 'lemur': Lemur('Hello')} id(data)=140451434388544 id(data['lemur'])=140451434394304

With PySide6 the Lemur object ends up as an empty list, dictionary keys are reordered and the dictionary is a different object:

tx data={'test_dictionary': 10, 'lemur': Lemur('Hello')} id(data)=140105873327040 id(data['lemur'])=140105873335856
rx data={'lemur': [], 'test_dictionary': 10} id(data)=140105873326848 id(data['lemur'])=140105990931392

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions