访问/修改Qt / QML中所有类型的实例

时间:2015-02-27 14:30:39

标签: c++ qt qml qt5

在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的{ {1}}功能。

注意:在我的实际用例中,实际上有几十个这样的实例,并且还有其他Text元素不是MyText的实例。

我对jQuery有一点经验,并希望有类似于jQuery选择器的东西,但我一直无法找到任何类似的东西。无论是QML还是C ++(或混合)解决方案都可以。

3 个答案:

答案 0 :(得分:2)

我想建议一个使用C ++的方法。 由于无法获得QML对象的基类,因此您可以将搜索基于objectName属性,可以在C ++中访问。

假设我们有基础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()等调用某些方法。

答案 1 :(得分:1)

我不确定你是否理解你的需要,但我会像这样使用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()
    }
}

答案 2 :(得分:0)

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 {
     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 
        }
    }
}