访问不同qml文件中的项目

时间:2017-08-02 19:57:11

标签: qt qml

我有几个qml文件,每个文件都在我的应用程序中定义一个屏幕。有时,一个屏幕上的操作应该更改不同屏幕上的项目。现在我通过设置来做到这一点 属性Item buttonId然后执行

for (var i = 0; i < buttonId.parent.children.length; i++) {
   buttonId.parent.children[i].state="inactive"
}

是否可以直接访问不同文件中的项目/对象,例如通过他们的身份?

2 个答案:

答案 0 :(得分:6)

正如 dtech 所说,你不能访问不同文件中的对象,因为它们还没有对象。

假设您有一个名为BlueSqare.qml

的文件
import QtQuick 2.0
Rectangle {
    id: root
    width: 100
    height: 100
    color: 'purple'
}

现在你有了main.qml

import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
    id: root
    width: 300
    height: 300
    visible: true
    Row {
        id: rowdi
        spacing: 3
        Repeater {
            model: 3
            delegate: BlueSquare {}
        }
    }
}

你会看到,它创建了我的BlueSquare中的三个,所以如果我设置root.color = 'blue',我想要更改哪一个是未定义的 - 或实际上它不是:因为我有另一个对象使用id: root中的main.qml,即ApplicationWindow,我会将其颜色设置为蓝色。

您可以看到:id只需要在一个文件中是唯一的,因此您只能通过id引用此一个文件中的对象。

可以免除此问题:您可以向上移动使用qml文件的文件树并引用它们的ID。

因此,如果您尝试在我的示例中rowdi中引用BlueSqure,则会引用安排它们的Row。这是可能的,因为您可以拥有一个定义明确的规则,您试图通过此id引用该对象。

如果在文件中找不到id(此处为:BlueSquare.qml),则尝试引用它,然后它将查找实例化对象的文件(此处为:main.qml)。如果它在那里找到它,搜索就结束了。如果找不到它,它会尝试移动一个文件 - 这在这里是不可能的,就像故事结束的main.qml一样。

但是如果可能的话应该避免这种情况。也许你想在其他地方重用BlueSquare,而你没有Row也恰好拥有id: rowdi。相反,你应该在实例化中注入引用。

import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
    id: root
    width: 300
    height: 300
    visible: true
    Row {
        id: rowdi
        spacing: 3
        property color squareColors: 'blue'
        Repeater {
            model: 3
            delegate: BlueSquare {
               color: rowdi.squareColors
            }
        }
    }
}

我们在这里定义了id rowdi我们定义它的文件,将数据注入BlueSquare

你也可以传递一个QtObject,它将所有值保存为模型。如果您要更改值,这将特别有用:

// MyModelCountingButton.qml

import QtQuick 2.0
import QtQuick.Controls 2.0
Button {
    property QtObject model // Better would be to be more specific the QtObject and have a object that guarantees to have your properties
    text: model ? model.count : '-'
    onClicked: {
        if (model) model.count++
    }
}

然后在main.qml

import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
    id: root
    width: 800
    height: 600
    visible: true

    QtObject {
        id: myCountingModel
        property int count: 0
    }

    MyModelCountingButton {
        id: button1
        model: myCountingModel
    }

    MyModelCountingButton {
        id: button2
        model: myCountingModel
    }
}

现在,您可以使用通用模型更改将影响其他对象的值,而无需引用自己文件之外的内容,从而提高了可重用性。

基本上,uppon实例化你告诉他们他们应该从哪里读取和存储他们的数据,如果这个地方在你的屏幕之间共享,你就赢了。

对于您的问题,最简单的方法是在模型中使用currentIndex - 属性,为每个屏幕分配一个索引,然后在文件中

// Screen.qml

[...]
Item {
    id: root
    property int index
    property QtObject indexObject
    Binding {
        target: root
        property: 'state'
        value: 'inactive'
        when: index !== indexObject.currentIndex
    }
}

并在main.qml

[...]
ApplicationWindow {
    [...]
    QtObject {
        id: indexObject
        property int currentIndex: 0
    }

    Screen {
        index: 0
        indexObject: indexObject
    }
    Screen {
        index: 1
        indexObject: indexObejct
    }
    [...]
}

或者您将屏幕视为:

[...]
Item {
    id: root
    property int index
    property int currentIndex
    signal turningActive // this must be emitted when you want to have this screen active.
    Binding {
        target: root
        property: 'state'
        value: 'inactive'
        when: index !== indexObject.currentIndex
    }
}

main.qml

[...]
ApplicationWindow {
    id: root
    [...]
    property int currentIndex: 0

    Screen {
        index: 0
        currentIndex: root.currentIndex
        onTuringActive: root.currentIndex = 0
    }
    Screen {
        index: 1
        currentIndex: root.currentIndex
        onTurningActive: root.currentIndex = 1
    }
    [...]
}

通常,如果只有少数属性,则创建声明其实例化的绑定。如果有大量数字,QtObject作为模型是有益的 只有当你真的真的确定将在哪个上下文中使用声明的组件时,您才可以考虑引用来自另一个文件的内容(例如,使用parent文件的根节点或使用需要在另一个文件中解析的id

答案 1 :(得分:4)

您无法访问&#34;不同的qml文件中的对象&#34;除非你有一个qml类型或单例的实例。

只有在尝试访问它的对象在其想要通过id访问的对象的范围内创建时,才可能通过id访问。

您有几个屏幕,只是将它们作为根qml对象的属性公开,然后由于动态范围,它们可以从整个应用程序访问,除非它们被具有相同名称的其他属性遮蔽。