是否可以从 C++ 访问 QML 锚点?
Is it possible to access QML anchors from C++?
从 C++ 代码创建 QML QQuickItems
时,是否可以 access/modify anchors
?
所有 anchors
属性在 QQuickItem
中声明为 Q_PRIVATE_PROPERTY
,我没有看到任何有用的方法。
或者我必须使用 signals/events 和 QLayout
自己实现 anchors
吗?
我需要的是例如:
Rectangle {
// ...
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
anchors.right: parent.right
anchors.rightMargin: -10
// ...
}
实际上有一个 class 用于锚点。即QQuickAnchors
位于QtQuick/private/qquickanchors_p_p.h
,处理它们属于QQuickItemPrivate
。但是由于两个 class 都不是 public API 的一部分,所以答案是:不,您不能从 C++ 中访问或修改锚点。
我会认为这个很好的 API 设计而不是限制。它迫使您在 QML 中管理视觉属性。因此,与其通过 new QQmlComponent()
从 C++ 创建 QML 组件,我建议直接在 QML 中使用已注册的自定义类型(可以使用 Repeater
and/or Loader
组件静态或动态完成),您可以从那里访问 Item
的 anchors
和所有其他视觉属性。
对于绑定到父级的锚点,我发现以下解决方案可以解决 "setting anchors.fill: parent
from c++" 当您无法在 QML 中实例化自定义类型时出现的问题(例如,您必须提供clean API 以动态创建 QML 对象):
class MyItem : public QQuickItem {
Q_OBJECT
public:
explicit MyItem(QQuickItem* parent){
if(parent){
connect(parent, SIGNAL(widthChanged()), this, SLOT(parentWidthChanged()));
connect(parent, SIGNAL(heightChanged()), this, SLOT(parentHeightChanged()));
setWidth(parent->width());
setHeight(parent->height());
}
else
qWarning() << "MyItem must be initialized with a parent.";
}
private slots:
void parentWidthChanged(){
setWidth(parentItem()->width());
}
void parentHeightChanged(){
setHeight(parentItem()->height());
}
};
可以按照类似的逻辑来模拟anchors.top
、anchors.bottom
等,并通过人工计算关联margin,也可能需要setX()
和setY()
来实现这个。
与之前的答案所表明的不同,它是可能的并且有有效的用例。所有 Qt 对象,甚至是私有对象,都有内省 API。您从 QML 引擎使用的那些 API。它们也可以在 C++ 中使用:
qvariant_cast<QObject*>(
item->property("anchors")
)->setProperty("top", otherItem->property("bottom"));
请注意,由于涉及某些线程,因此存在竞争条件。
QML 仅支持模型列表。显示树或 table 等其他结构要么实施不当(QtQuickControls 1.x),要么效率低得令人难以置信(递归转发器)。对于一些数据结构,C++也是正确实现延迟加载的唯一途径。 QML Loader
走了很长一段路,但不是一路走来。
从 C++ 代码创建 QML QQuickItems
时,是否可以 access/modify anchors
?
所有 anchors
属性在 QQuickItem
中声明为 Q_PRIVATE_PROPERTY
,我没有看到任何有用的方法。
或者我必须使用 signals/events 和 QLayout
自己实现 anchors
吗?
我需要的是例如:
Rectangle {
// ...
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
anchors.right: parent.right
anchors.rightMargin: -10
// ...
}
实际上有一个 class 用于锚点。即QQuickAnchors
位于QtQuick/private/qquickanchors_p_p.h
,处理它们属于QQuickItemPrivate
。但是由于两个 class 都不是 public API 的一部分,所以答案是:不,您不能从 C++ 中访问或修改锚点。
我会认为这个很好的 API 设计而不是限制。它迫使您在 QML 中管理视觉属性。因此,与其通过 new QQmlComponent()
从 C++ 创建 QML 组件,我建议直接在 QML 中使用已注册的自定义类型(可以使用 Repeater
and/or Loader
组件静态或动态完成),您可以从那里访问 Item
的 anchors
和所有其他视觉属性。
对于绑定到父级的锚点,我发现以下解决方案可以解决 "setting anchors.fill: parent
from c++" 当您无法在 QML 中实例化自定义类型时出现的问题(例如,您必须提供clean API 以动态创建 QML 对象):
class MyItem : public QQuickItem {
Q_OBJECT
public:
explicit MyItem(QQuickItem* parent){
if(parent){
connect(parent, SIGNAL(widthChanged()), this, SLOT(parentWidthChanged()));
connect(parent, SIGNAL(heightChanged()), this, SLOT(parentHeightChanged()));
setWidth(parent->width());
setHeight(parent->height());
}
else
qWarning() << "MyItem must be initialized with a parent.";
}
private slots:
void parentWidthChanged(){
setWidth(parentItem()->width());
}
void parentHeightChanged(){
setHeight(parentItem()->height());
}
};
可以按照类似的逻辑来模拟anchors.top
、anchors.bottom
等,并通过人工计算关联margin,也可能需要setX()
和setY()
来实现这个。
与之前的答案所表明的不同,它是可能的并且有有效的用例。所有 Qt 对象,甚至是私有对象,都有内省 API。您从 QML 引擎使用的那些 API。它们也可以在 C++ 中使用:
qvariant_cast<QObject*>(
item->property("anchors")
)->setProperty("top", otherItem->property("bottom"));
请注意,由于涉及某些线程,因此存在竞争条件。
QML 仅支持模型列表。显示树或 table 等其他结构要么实施不当(QtQuickControls 1.x),要么效率低得令人难以置信(递归转发器)。对于一些数据结构,C++也是正确实现延迟加载的唯一途径。 QML Loader
走了很长一段路,但不是一路走来。