在QML中,我有一个自定义对象类型(一个单独的QML文件),我想要一种访问和/或修改该类型的每个实例的方法。举个非常简单的例子:
MyText.qml:
Text {
height: 100
width: 100
color: "red"
function logStuff() {
console.log("This is MyText")
}
}
SomePage.qml:
MyText {
id: text1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "foo"
}
MyText {
id: text2
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "bar"
}
当事件发生时(例如,单击SomePage.qml上的按钮或发出信号),我希望能够将MyText的所有实例更改为一个属性具有相同的值,或者调用每个MyText的logStuff()
函数。
注意:在我的实际用例中,实际上有几十个这样的实例,还有其他不是MyText实例的Text元素。
我对jQuery有一点经验,希望能有类似于jQuery选择器的东西,但我一直找不到任何类似的东西。QML或C++(或混合)解决方案都可以。
我想推荐一个使用C++的方法。由于无法获得QML
对象的基类,因此可以基于C++中可访问的objectName
属性进行搜索。
假设我们有一个基本的QML
对象:
import QtQuick 2.3
Item {
id: base
objectName: "BaseItem"
property int someValue: 0
onSomeValueChanged: {
console.log("'someValue' was changed to " + someValue + " for " + base);
}
}
以及另一个QML文件,其中使用了这些对象:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
visible: true
width: 300
height: 300
id: mainWindow
Base {
id: derived1
}
Base {
id: derived2
}
Base {
id: derived3
}
}
其思想是所有派生对象从基类继承相同的objectName
。
所以现在您可以简单地在C++
:中找到所有对象
QObject *root = engine.rootObjects().first();
QList<QObject *> list = root->findChildren<QObject *>("BaseItem");
qsrand(QTime::currentTime().msec());
foreach(QObject *item,list) {
item->setProperty("someValue",qrand());
}
这里我只是更改了属性,但您也可以用QMetaObject::invokeMethod()
等调用一些方法。
我不确定是否理解您的需求,但我只想使用这样的Connections元素:
SomePage.qml:
MyText {
id: text1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "foo"
Connections {
target: senderItemId
onFooChanged: logStuff()
}
}
MyText {
id: text2
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "bar"
Connections {
target: senderItemId
onFooChanged: logStuff()
}
}
Qt中没有API调用(我可以找到),但您可以使用C++中的QObject::children()和QMetaObject按类型找到所有QML QObject。下面是一个实现示例。
QList<QObject *> MySingleton::findObjectsOfComponent(QObject *parent, QQmlComponent *component) const
{
auto object = component->create(QQmlEngine::contextForObject(parent));
auto foundObjects = findObjectsOfObject(parent, object);
delete object;
return foundObjects;
}
QList<QObject *> MySingleton::findObjectsOfObject(QObject *parent, const QObject *object) const
{
auto className = object->metaObject()->className();
QList<QObject*> items;
for(auto child : parent->children()) {
if(child->metaObject()->className() == className) {
items.append(child);
}
items.append(findObjectsOfObject(child, object));
}
return items;
}
然后,您应该将MySingleton注册为QML单例,并使用Component来查找类型。
Component {
id: errorLabelComponentId
ErrorLabel {}
}
Button {
onClicked: {
//Un-ignore all error labels
var errorLabels = MySingleton.findObjectsOfComponent(pageId, errorLabelComponentId)
for(var i in errorLabels) {
//ignoreError is a property of ErrorLabel {}
errorLabels[i].ignoreError = false
}
}
}