I've got class that inherits from QQuickItem
and inside I'm operating on its width
height
properties. I'm also exposing my own properties.
class MyQQuickItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QUrl source MEMBER m_source NOTIFY sourceChanged)
public:
explicit MyQQuickItem(QQuickItem *a_parent = Q_NULLPTR);
~PDFPage();
signals:
void sourceChanged(const QUrl a_source);
private:
QUrl m_source;
};
In qml:
...
MyQQuickItem
{
width: parent.width / 2
height: parent.height
source: "someSource"
Component.onCompleted
{
console.log("component onCompleted");
}
}
When sourceChanged
is emmited I'm working on width
height
properties, but with the first emit they are not initialized yet, and Component.onCompleted
is called after my NOTIFY signal.
I can check if component is ready before getting width
and height
by calling isComponentComplete and execute my code when it is, but I can't find out when it happens and the initial value of source
is skipped when it is not.
Of course I could create slot 'itemReady'
and call it from Component.onCompleted
, but I have many QMLs using my class and I will create more in the future, so I don't want to make copy-paste job.
I also do not want to set the source in Component.onCompleted
.
Connecting to widthChanged
, and heightChanged
signals isn't also good idea, because I'm resizing my item very frequently, and I don't want to execute my code then.
Is there any way to get completed
signal from C++?
EDIT:
I did as @Mitch said - overriten componentComplete method and inside, called it's base class equavilent. isComponentComplete()
returns true, but I'm still getting 0 from width()
and height()
methods:
void MyQQuickItem::componentComplete()
{
QQuickItem::componentComplete();
if(isComponentComplete())
{
qDebug() << "c++: oncompleted, width,height: " << width() << height(); //gives 0,0
}
}
Actually I figured out that Component.onCompleted
in QML prints 0's too:
...
MyQQuickItem
{
width: parent.width / 2
height: parent.height
source: "someSource"
Component.onCompleted
{
console.log("component onCompleted width, height: ", width, height); //it gives 0 too
}
}
@derM Component.onCompleted
is not emmited by QQuickItem::componentComplete()
directly, because it prints its log after the qDebug in c++ above.
So, although it is ready, properties are not initialized.
EDIT2:
Finally I've solved it. The Window was guilty, because it uses contentItem
as the parent of his childrens, and in MyQQuickItem Component.onCompleted
width
and height
of contentItem
(his parent) are 0.
When I do so:
Window
{
id: wnd
width: 640
height: 480
Component.onCompleted:
{
console.log("Window completed: ", this, width, height);
console.log("windowContentItem: ", contentItem, width, height);
}
MyQQuickItem
{
width: parent.width
height: parent.height
Component.onCompleted:
{
console.log("MyQQuickItem completed: ", this, width, height);
console.log("MyQQuickItem parent: ", parent, parent.width, parent.height);
}
}
}
It prints:
qml: Window completed: QQuickWindowQmlImpl(0x345b5eb4d0) 640 480
qml: windowContentItem: QQuickRootItem(0x345e2cdec0) 640 480
qml: MyQQuickItem completed: MyQQuickItem(0x345b5b99e0) 0 0
qml: MyQQuickItem parent: QQuickRootItem(0x345e2cdec0) 0 0
So MyQQuickItem
parent
is Window
's contentItem
. When I replace
width: parent.width
height: parent.height
to:
width: wnd.width
height: wnd.height
It works perfectly, and in my void MyQQuickItem::componentComplete()
I've got width
and height
initialized as expected.
One thing that I do not understand is why in Window
onCompleted
, contentItem
size is correct, but in MyQQuickItem
onCompleted
the size is 0,0. If anyone could explain it to me, I would be grateful :P