如何找出 QQuickItem-derived class object 何时初始化?
How to find out when the QQuickItem-derived class object is initialized?
我有 class 继承自 QQuickItem
并且在内部我正在操作它的 width
height
属性。我也暴露了自己的属性。
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;
};
在 qml 中:
...
MyQQuickItem
{
width: parent.width / 2
height: parent.height
source: "someSource"
Component.onCompleted
{
console.log("component onCompleted");
}
}
当 sourceChanged
发出时我正在处理 width
height
属性,但是第一次发出时它们还没有初始化,之后调用 Component.onCompleted
我的通知信号。
我可以在获取 width
和 height
之前检查组件是否准备就绪,方法是调用 isComponentComplete 并在准备就绪时执行我的代码,但我无法确定它何时发生并且 source
的初始值在不是时被跳过。
当然我可以创建插槽 'itemReady'
并从 Component.onCompleted
调用它,但是我有很多 QML 使用我的 class 并且我将来会创建更多,所以我不' 想做 copy-paste 工作。
我也不想在Component.onCompleted
中设置源。
连接到 widthChanged
和 heightChanged
信号也不是个好主意,因为我经常调整我的项目的大小,然后我不想执行我的代码。
有什么方法可以从 C++ 获取 completed
信号吗?
编辑:
我按照@Mitch 所说的那样做了 - 覆盖 componentComplete 方法并在内部调用它的基础 class 等效。 isComponentComplete()
returns 是的,但我仍然从 width()
和 height()
方法中得到 0:
void MyQQuickItem::componentComplete()
{
QQuickItem::componentComplete();
if(isComponentComplete())
{
qDebug() << "c++: oncompleted, width,height: " << width() << height(); //gives 0,0
}
}
实际上我发现 QML 中的 Component.onCompleted
也打印 0:
...
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
不是由 QQuickItem::componentComplete()
直接发出的,因为它在上面的 c++ 中的 qDebug 之后打印了它的日志。
因此,虽然准备就绪,但属性尚未初始化。
编辑2:
终于解决了。 Window 是有罪的,因为它使用 contentItem
作为他孩子的 parent,而在 MyQQuickItem Component.onCompleted
width
和 height
中 contentItem
(他的parent)是0.
当我这样做时:
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);
}
}
}
它打印:
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
所以 MyQQuickItem
parent
是 Window
的 contentItem
。当我替换
width: parent.width
height: parent.height
至:
width: wnd.width
height: wnd.height
它运行完美,在我的 void MyQQuickItem::componentComplete()
中,我已经按预期初始化了 width
和 height
。
我不明白的一件事是为什么在 Window
onCompleted
、contentItem
中尺寸是正确的,但在 MyQQuickItem
onCompleted
中尺寸是正确的0,0。如果有人能给我解释一下,我将不胜感激:P
Qt code uses componentComplete()
像这样:
void QQuickControl::componentComplete()
{
Q_D(QQuickControl);
QQuickItem::componentComplete();
d->resizeContent();
// ...
}
您可以做类似的事情,将 resizeContent()
替换为适用于 width
和 height
的函数。假设每当 source
更改时也会调用该函数,则您需要 isComponentComplete()
检查。使用这种方法,您应该不会有任何问题。
可以继承QQmlParserStatus并实现componentComplete()。
class MyQQuickItem : public QQuickItem, public QQmlParserStatus
{
Q_OBJECT
Q_PROPERTY(QUrl source MEMBER m_source NOTIFY sourceChanged)
public:
explicit MyQQuickItem(QQuickItem *a_parent = Q_NULLPTR);
~PDFPage();
void classBegin();
void componentComplete();
signals:
void sourceChanged(const QUrl a_source);
private:
QUrl m_source;
};
componentComplete() 将由 QML 引擎自动调用。
我有 class 继承自 QQuickItem
并且在内部我正在操作它的 width
height
属性。我也暴露了自己的属性。
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;
};
在 qml 中:
...
MyQQuickItem
{
width: parent.width / 2
height: parent.height
source: "someSource"
Component.onCompleted
{
console.log("component onCompleted");
}
}
当 sourceChanged
发出时我正在处理 width
height
属性,但是第一次发出时它们还没有初始化,之后调用 Component.onCompleted
我的通知信号。
我可以在获取 width
和 height
之前检查组件是否准备就绪,方法是调用 isComponentComplete 并在准备就绪时执行我的代码,但我无法确定它何时发生并且 source
的初始值在不是时被跳过。
当然我可以创建插槽 'itemReady'
并从 Component.onCompleted
调用它,但是我有很多 QML 使用我的 class 并且我将来会创建更多,所以我不' 想做 copy-paste 工作。
我也不想在Component.onCompleted
中设置源。
连接到 widthChanged
和 heightChanged
信号也不是个好主意,因为我经常调整我的项目的大小,然后我不想执行我的代码。
有什么方法可以从 C++ 获取 completed
信号吗?
编辑:
我按照@Mitch 所说的那样做了 - 覆盖 componentComplete 方法并在内部调用它的基础 class 等效。 isComponentComplete()
returns 是的,但我仍然从 width()
和 height()
方法中得到 0:
void MyQQuickItem::componentComplete()
{
QQuickItem::componentComplete();
if(isComponentComplete())
{
qDebug() << "c++: oncompleted, width,height: " << width() << height(); //gives 0,0
}
}
实际上我发现 QML 中的 Component.onCompleted
也打印 0:
...
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
不是由 QQuickItem::componentComplete()
直接发出的,因为它在上面的 c++ 中的 qDebug 之后打印了它的日志。
因此,虽然准备就绪,但属性尚未初始化。
编辑2:
终于解决了。 Window 是有罪的,因为它使用 contentItem
作为他孩子的 parent,而在 MyQQuickItem Component.onCompleted
width
和 height
中 contentItem
(他的parent)是0.
当我这样做时:
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);
}
}
}
它打印:
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
所以 MyQQuickItem
parent
是 Window
的 contentItem
。当我替换
width: parent.width
height: parent.height
至:
width: wnd.width
height: wnd.height
它运行完美,在我的 void MyQQuickItem::componentComplete()
中,我已经按预期初始化了 width
和 height
。
我不明白的一件事是为什么在 Window
onCompleted
、contentItem
中尺寸是正确的,但在 MyQQuickItem
onCompleted
中尺寸是正确的0,0。如果有人能给我解释一下,我将不胜感激:P
Qt code uses componentComplete()
像这样:
void QQuickControl::componentComplete()
{
Q_D(QQuickControl);
QQuickItem::componentComplete();
d->resizeContent();
// ...
}
您可以做类似的事情,将 resizeContent()
替换为适用于 width
和 height
的函数。假设每当 source
更改时也会调用该函数,则您需要 isComponentComplete()
检查。使用这种方法,您应该不会有任何问题。
可以继承QQmlParserStatus并实现componentComplete()。
class MyQQuickItem : public QQuickItem, public QQmlParserStatus
{
Q_OBJECT
Q_PROPERTY(QUrl source MEMBER m_source NOTIFY sourceChanged)
public:
explicit MyQQuickItem(QQuickItem *a_parent = Q_NULLPTR);
~PDFPage();
void classBegin();
void componentComplete();
signals:
void sourceChanged(const QUrl a_source);
private:
QUrl m_source;
};
componentComplete() 将由 QML 引擎自动调用。