TL;DR
How do I correctly pass information, wrapped as a QObject
to QML in a signal that might be emitted with high frequency, reducing overhead, ensuring the object/reference outlives at least the execution of the connected slots?
I have a C++ QObject registered as QML type. This object has some signal
void someSignal(InformationQObject* someInformation)
in which I don't pass all the information in seperate parameters but in one object - similar to the signals found e.g. in the MouseArea
whith e.g. the signal
void clicked(QQuickMouseEvent *mouse)
Now I am wondering about the right lifetime management of this someInformation
.
So far, in my object, I have a member:
InformationQObject* m_lastInformation
and to send the signal I use:
void sendMySignal(/* possible params */)
{
delete m_lastInformation
m_lastInformation = new InformationQObject(/* right params here */)
emit someSignal(m_lastInformation)
}
Now this seems wrong.
Reasons: If you look at the implementation of the QQuickMouseArea
they do it differently. Seemingly they don't create a new object for each event but recycle the existing one, seemingly. I find it hard to follow all their sources but I think this comment from one of their files gives a good reason:
QQuickPointerEvent is used as a long-lived object to store data related to an event from a pointing device, such as a mouse, touch or tablet event, during event delivery. It also provides properties which may be used later to expose the event to QML, the same as is done with QQuickMouseEvent, QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be delivered at a time, this class is effectively a singleton. We don't worry about the QObject overhead because the instances are long-lived: we don't dynamically create and destroy objects of this type for each event.
But this is where it gets to complicated for me to see through, how they do it. This comment is regarding a QQuickPointerEvent
. There exists a QQuickPointerMouseEvent
. In their signal they pass a QQuickMouseEvent*
The latter is a pointer to one of their members QQuickMouseEvent quickMouseEvent
.
At some point, somehow, this pointer becomes invalid in QML
MouseArea {
anchors.fill: parent
property var firstEvent
onClicked: {
if (firstEvent === undefined) firstEvent = mouse
console.log(mouse.x, mouse.y)
console.log(firstEvent.x, firstEvent.y) // -> TypeError on second and consecutive clicks.
}
}
So there must be some magic happening, that I don't understand.