【问题标题】:Qt: accessing elements arbitrarily by ID in QMLQt:在QML中通过ID任意访问元素
【发布时间】:2016-12-30 00:09:28
【问题描述】:

我想通过主文件中的 ID 访问我的 QML 元素,但它不起作用。在我的测试(案例)环境中,我有 2 个文件:

  1. main.qml,这是我要通过ID访问的文件
  2. Accounts.qml,这是定义我的元素的文件

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0

Item {

    Accounts {
        id: accounts
    }
    Component.onCompleted: {
        console.log(accounts);
        console.log(accounts.accounts_pane);
        console.log(accounts.list_area);
        console.log(accounts.accounts_pane.list_area.list_column.list_identities.model);
    }
}

Accounts.qml

import QtQuick 2.7
import QtQuick.Controls 2.0

Pane {
    id: accounts_pane
    anchors {
        fill: parent
    }    
    Rectangle {
        id: list_area
        border.color: "black"
        border.width: 2
        anchors {
            left: parent.left
            right: parent.right
            top: parent.top
            bottom: parent.bottom
        }
        Column {
            id: list_column
            ListView {
                id: list_identities
                width: list_area.width
                height: 200
                model: ListModel {
                    ListElement {
                        name: "Bill Smith"
                        number: "555 3264"
                    }
                    ListElement {
                        name: "John Brown"
                        number: "555 8426"
                    }
                }
                delegate: Text {
                    text: name + ',' + number
                }
            }
        }
    }
}

所以,我想从 main.qml 文件更改帐户的模型(不同的公司使用不同的帐户),我需要使用 Javascript 来完成。 (我的模型是一个 C++ 类,在 QML 引擎中注册,但我将使用 Javascript 来切换不同的模型对象)。据我了解,访问模型的符号应该是这样的:

accounts.accounts_pane.list_area.list_column.list_identities.model

但是,在测试时,使用 console.log():

    console.log(accounts);
    console.log(accounts.accounts_pane);
    console.log(accounts.list_area);
    console.log(accounts.accounts_pane.list_area.list_column.list_identities.model);

我无法通过 Accounts.qml 中定义的 Pane {} 元素。 qmlscene 的输出显示了这些错误:

 hier $ qmlscene main.qml 
qml: QQuickPane(0x13b85f0)
qml: undefined
qml: undefined
file:///QT_snippets/qmlscenes/hier/main.qml:13: TypeError: Cannot read property 'list_area' of undefined

如何在 main.qml 文档中通过 ID 任意访问 QML 元素?

【问题讨论】:

    标签: qt qml qt5


    【解决方案1】:

    您最好只使用 id 来访问同一 QML 文件中的对象。也可以通过 id 访问对象,只要您处于嵌套在具有 id 的组件内的组件范围内,只要它没有被任何具有相同名称的东西所遮蔽。简而言之,id 只能从内部访问,而不能从外部访问,后者是您的使用场景。

    如果您想访问其他 QML 文件中的元素,它们必须作为属性公开。此外,根 QML 文件中定义的属性将在整个项目中可见,只要同名的属性隐藏它。

    将 QML 文件中的每个对象都视为私有的,而属性是公共的。如果您想访问其中一个私有对象,请将其作为属性公开。

    property Item someItem : _item
    Item { id: _item } 
    

    在您的情况下,accounts_pane 是多余的,因为它将与 accounts 相同 - 它是同一个对象。

    如果您直接公开list_identities,则无需公开之前的所有对象即可访问它:

    accounts.accounts_pane.list_area.list_column.list_identities.model // no need
    accounts.list_identities.model // all you need
    

    此外,您可以将特定对象的特定属性公开为别名:

    // in Accounts.qml
    property alias model: list_identities.model
    // then you can simply
    accounts.model
    

    最后,认为这种方法是错误的,你不应该将所有东西都暴露给外部使用,你应该定义一个接口来控制每个 QML 组件的内部。

    组件的接口包含它定义的所有顶级属性。

    【讨论】:

    • 非常感谢!关于接口,你如何定义一个?它是 JavaScript 函数吗?
    • @Nulik - 它是属性、函数或别名的集合 - 无论您需要什么。例如,如果您只需要能够设置模型,则将其公开为别名。
    猜你喜欢
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多