What is faster: c++ single signal or multiple properties
-
Hi,
I have QML component that is managed from c++ side. There are couple (5-10) parameters (properties) of underlaying c++ class whose affects the component.
So let's component looks like://myComp.qml Item { Text ( id: text1; text: ""; y: 0 } Text ( id: text2; text: "" } Rectangle { id: rect1; x: 0; width: 1 } MyCompObj { id: obj } // underlaying c++ class (QObject) }
All those properties above are managed by that c++ class.
So what is the better approach:- To have corresponding properties in c++ and:
// .... Text ( id: text1; text: obj.text1; y: obj.textY1 } // ... and so
- or to send single signal from c++ object (i.e.
emit changed()
)
and update all properties in single function (QML slot) from invokable methods of c++ object:
MyCompObj { id: obj onChanged: { text1.text = obj.text1() text2.text = obj.text2() // etc... } }
All of those parameters change at once for single instance and there can be many instances of MyComp in the app (100-500).
What do You think?
-
I think I'm interested to read the results of your test/performance metrics :-) - I'd say you do what works for you though I would have a preference for a single property / connect per c++ property.
I haven't hit any performance bottlenecks myself yet, though I am not creating a game or anything.
I have some canvas work and my classes update data quite a lot but drawing is probably the most intensive thing I do. I haven't had the need to investigate the performance of sig/slots...yet. So far I'm loving them.As far as maintenance and readability I would totally use (what I think is your option one) single data / signal design.
My typical c++ class (for your example):
Q_PROPERTY(QString Text1 READ getText1 WRITE setText1 NOTIFY text1Changed )
Q_PROPERTY(QString Text2 READ getText2 WRITE setText2 NOTIFY text2Changed )
..
implement get, set and declare changed signals... + work in your app thread to access class from, instance as "CppClass" in QML...Component.onCompleted: { // initial one time load from c++
root.qmlText1Property = CppClass.Text1;
root.qmlText2Property = CppClass.Text2;
}
Connections {
target: CppClass;
onText1Changed: root.qmlText1Property = CppClass.Text1;
onText2Changed: root.qmlText2Property = CppClass.Text2;
}I don't mix my GUI with my C++ class, that just stores the object state/data as I have no need to store the screen coordinates in my backend code... but maybe you are needing that? I have an application mainly driven by sensors and network traffic so the frontend merely updates and reacts from application state but some parts (app configuration/preferences) as wired to go back and update the data in c++ objects.
My preference is to only update what is changing and not send the entire object every-time, my app is not very heavy hitting but quite chatty frequently updating the frontend so I will choose to just to change the one property on changes. Some of my data for example only every loads once on completed or very ad hoc (serial number changes etc)
But again I'd say just do what works for you / you are comfortable with maintaining. Not sure if this helps...
-
@6thC Thank You for advice.
Even if I thought first to use QML function to update all, this property per property approach was attractive due to selectiveness, so You convinced me in that.
Even if it will use more RAM it should be faster.
But I found there is a third possibility...
To have single Item created from C++ asQQuickItem
subclass, that will perform function of both above (QML item and C++ object)
In constructor ofMyItemObject
I can create necessary children items and manage them directly then:MyItemObject::MyItemObject(QQuickItem* parent) : QQuickItem(parent) { QQmlEngine engine; QQmlComponent comp(&engine, this); comp.setData("import QtQuick 2.7; Rectangle { }", QUrl()); m_itemRect = qobject_cast<QQuickItem*>(comp.create()); m_itemRect->setParentItem(this); m_itemRect->setProperty("color", qApp->palette().text().color()); m_itemRect->setWidth(0.3); m_itemRect->setHeight(6.0); comp.setData("import QtQuick 2.7; Text { font { family: \"MyFont\"; pixelSize: 7 }}", QUrl()); m_itemText1 = qobject_cast<QQuickItem*>(comp.create()); m_itemText1->setParentItem(this); m_itemText1->setProperty("text", QString("\uf4be")); m_itemText1->setY(20.0); }
This way I have access to some properties directly (
visible
,x
,y
,width
and so).I'm aware, it is not QML way and it requires more "dirty" work but for my case it seems to be best solution.
Anyway, I will sleep with that fist.... -
Cheers mate, thanks for the feedback. Good luck with whatever you are building!
If you do find that does get a bit much - maybe just keep QML in mind if it's at a point of frustration / giving up.
I have had great success in keeping my visual disconnected - no adverse affects accessing my c++ object's data etc. - I don't think I'd have the patience to code my QML like that! Already I see too much character escaping etc, no code highlighting... I do feel you'd hit yourself with a bit of an unnecessary development/maintenance handicap.
You can expose to c++ those QML object properties (visible, x, y, width) etc... I was just saying I don't as my GUI mostly reacts to my data / C++ objects and I don't need this information in my c++ that does receive QML Signals.
Anyhow, good luck!
-
@6thC Thanks a million for advices.
I did it in pure C++, it didn't pain much...
But honesty, there was a moment when I "ported"Repeater
with 14 elements into C++ where visibility property was just a single condition. I was close to back to QML when I had to write a loop and take care myself about when this condition changes and apply it to all elements (again in loop).
But later when I wrote all logic in C++ - it was really much, much easier an more efficient.
But probably, this case of mine is the one in a million when this pure C++ approach justifies itself.
Literally, I have only those two statements ofQQmlComponent::setData()
(one in loop) and I'm operating on x, y, width, height and visibility which are accessible directly.
In other places of my app I'm keeping QML and C++ separately.I did measurements of above (C++), but they say nothing until I will implement exactly the same using QML. In spare time maybe...
Once more, thank You for feedback.
-
Anytime mate!
I am with you on keeping app logic in C++. QML and C++ with Signals and Slots are just such a good combination!
For my project and so far I've not had a design that needs that level of remote control.
I don't know if I've been so genuinely excited to use a technology as Signals and Slots.
So far I've got no performance bottlenecks - yet but I am keenly interested to see what it takes until I need to start doing multi-threading. Also in spare time...