【发布时间】:2018-03-01 21:23:16
【问题描述】:
我有一个继承自 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 属性,但在第一次发出时,它们尚未初始化,并且在我的NOTIFY 信号之后调用Component.onCompleted。
我可以通过调用isComponentComplete 在获取width 和height 之前检查组件是否准备就绪,并在准备就绪时执行我的代码,但我无法找出它何时发生以及source 的初始值不是时跳过。
当然我可以创建插槽'itemReady' 并从Component.onCompleted 调用它,但是我有很多 QML 使用我的类,我将来会创建更多,所以我不想做复制粘贴工作。
我也不想在Component.onCompleted 中设置源。
连接到widthChanged 和heightChanged 信号也不是一个好主意,因为我经常调整我的项目大小,并且我不想执行我的代码。
有没有办法从 C++ 中获取completed 信号?
编辑:
我按照@Mitch 所说的做了-覆盖了componentComplete 方法和内部,称它为等效的基类。 isComponentComplete() 返回 true,但我仍然从 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() emmited,因为它在上面c++ 中的qDebug 之后打印了它的日志。
因此,虽然它已准备就绪,但属性并未初始化。
EDIT2:
终于解决了。 Window 是有罪的,因为它使用 contentItem 作为他孩子的父母,而在 MyQQuickItem 中 Component.onCompleted width 和 height 的 contentItem(他的父母)是 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 按预期初始化。
我不明白的一件事是为什么在WindowonCompleted,contentItem 大小是正确的,但在MyQQuickItem onCompleted 中,大小是 0,0。如果有人能给我解释一下,我将不胜感激:P
【问题讨论】:
-
MCVE 仍然丢失。它将包含一个完整的 QML 文件,以便整个设置实际重现问题。
-
@derM 检查 EDIT2