Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-2027

Different QObject wrappers in constructor with parent vs QChildEvent

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Do
    • P4: Low
    • None
    • 5.15.1
    • Shiboken
    • None

    Description

      I have a QObject subclass that is installed as an event filter to watch for QChildEvents for when children are added to/removed from a particular parent QObject. This watcher stores the children in a list for use later. This works fine when the children have their parent set outside of the constructor. However, I noticed that if the children have their parents set within the constructor, the PySide2.QtCore.QObject wrapper returned by QChildEvent.child() is different than the one used to hold the constructed object in the outer scope. Worse still, the object returned by QChildEvent.child() appears to have its underlying C++ object destroyed at least in some instances once the final object has been constructed.

      Here is a small Python test (using pytest-qt) that demonstrates the issue:

      from PySide2.QtCore import QEvent, QObject

      def test_child():

          class Watcher(QObject):

              def _init_(self, parent=None):

                  super()._init_(parent)

                  self.child = None

              def eventFilter(self, watched, event):

                  if event.type() == QEvent.Type.ChildAdded:

                      child = event.child()

                      print(f'event.child(): {child}')

                      self.child = child

                  return super().eventFilter(watched, event)

          parent = QObject()

          watcher = Watcher()

          parent.installEventFilter(watcher)

          child = QObject(parent)

          print(f'child: {child}')

          print(f'parent.children(): {parent.children()}')

          assert child is watcher.child

      This can be run like so:

      python -m pytest -s test_child.py

      Which in my environment produces output like this:

      ====================================== test session starts =======================================
      platform linux – Python 3.6.9, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
      PySide2 5.15.1 – Qt runtime 5.15.1 – Qt compiled 5.15.1
      rootdir: /src/temp
      plugins: mock-3.6.1, hypothesis-6.31.6, qt-4.0.2, xvfb-2.0.0
      collected 1 item

      test_child.py event.child(): <PySide2.QtCore.QObject(0x24b6f70) at 0x7f9e1a3ed048>
      child: <PySide2.QtCore.QObject(0x24b6f70) at 0x7f9e1a3e6a08>
      children: [<PySide2.QtCore.QObject(0x24b6f70) at 0x7f9e1a3e6a08>]
      F

      ============================================ FAILURES ============================================
      ___________________________________________ test_child ___________________________________________

      def test_child():
      def _init_(self, parent=None):
      super()._init_(parent)

      self.child = None

      class Watcher(QObject):
      def eventFilter(self, watched: QObject, event: QEvent) -> bool:
      if event.type() == QEvent.Type.ChildAdded:
      child = event.child()
      print(f'event.child(): {child}')
      self.child = child

      return super().eventFilter(watched, event)

      app = QCoreApplication()
      parent = QObject()

      watcher = Watcher()
      parent.installEventFilter(watcher)

      child = QObject(parent)
      print(f'child: {child}')
      print(f'children: {parent.children()}')

      > assert child is watcher.child
      E AssertionError: assert <PySide2.QtCore.QObject(0x24b6f70) at 0x7f9e1a3e6a08> is <[RuntimeError('Internal C++ object (PySide2.QtCore.QObject) already deleted.',) raised in repr()] QObject object at 0x7f9e1a3ed048>
      E + where <[RuntimeError('Internal C++ object (PySide2.QtCore.QObject) already deleted.',) raised in repr()] QObject object at 0x7f9e1a3ed048> = <test_child.Watcher(0x24a8440) at 0x7f9e1a3e6948>.child

      test_child.py:29: AssertionError
      ==================================== short test summary info =====================================
      FAILED test_child.py::test_child - AssertionError: assert <PySide2.QtCore.QObject(0x24b6f70) at...
      ======================================= 1 failed in 0.08s ========================================

      Attachments

        1. pyside2027.py
          2 kB
        2. test_child.py
          0.7 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            kleint Friedemann Kleint
            michael.siegrist Michael Siegrist
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes