Details
-
Bug
-
Resolution: Won't Do
-
P4: Low
-
None
-
5.15.1
-
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 ========================================