【问题标题】:QML - How to get children in an item?QML - 如何让孩子进入项目?
【发布时间】:2019-04-04 16:01:53
【问题描述】:

我对 QML 中的项目有疑问。我想得到一个项目的孩子,但它似乎在第一个元素中工作。

详细代码如下:

我有一个带有列表自定义组件 AAA_Styles 的 gridview

GridView{
    id: grdViewDeviceControl
    clip: true
    interactive: true
    ScrollIndicator.vertical: ScrollIndicator{}
    cellWidth: 200
    cellHeight: 300

    model: ListModel{}

    delegate: Item {
        width: grdViewDeviceControl.cellWidth
        height: grdViewDeviceControl.cellHeight
        AAA_Styles{
            id: deviceControl
            objectName: "deviceControl"
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            name: Names
            subname: Subnames
    }
}

我的自定义AAA_RTS是一个QML组件,有一些功能,例如:
- function_a()
- 函数_b()
我使用

在模型中添加了 2 个项目

grdViewDeviceControl.model.append()

我确保模型有我添加的数据,因为它出现在我的设计中并且 gridview 的计数是 2 个元素

console.log(grdViewDeviceControl.count) //结果是2

之后,我尝试使用按钮的信号 onRelease 中的方法让每个元素访问它们可用的功能:

onReleased: {
    console.log("number of item: " + grdViewDeviceControl.count)
    var myRTS = grdViewDeviceControl.contentItem.children[0]
    console.log(myRTS)
    console.log(myRTS.children[0])
    myRTS = grdViewDeviceControl.contentItem.children[1]
    console.log(myRTS)
    console.log(myRTS.children[1])
}

控制台上的结果:

qml:项目数:2
qml: QQuickItem(0x9828f60)
qml: AAA_Styles_QMLTYPE_0_QML_112(0x9829070, "deviceControl")
qml: QQuickItem(0x5554140)
qml: 未定义

使用第一个元素 grdViewDeviceControl.contentItem.children[0],我访问 function_afunction_b 成功但是当我使用第二个时出现错误

TypeError:无法调用未定义的方法“function_a”

那么谁能告诉我为什么我错了以及如何解决它?

非常感谢您的帮助!

【问题讨论】:

  • 访问视图中的项目是一种不好的做法,因为它会带来诸如您指出的问题,而您应该与模型信息进行交互。为什么要访问这些项目?
  • 是的,我不知道最好的方法。感谢您的推荐以及如何访问模型?我想我必须在 gridview 之外创建一个模型并通过 id 访问它
  • 没错,检查我的旧答案stackoverflow.com/a/55318200/6622587
  • 您指出的可能解决方案可以工作,但我没有分析它,因为对我来说这不是正确的解决方案,因为它难以维护,例如,如果您更改组件,您将不得不修改代码的另一部分。也就是说,您可能的解决方案是一个临时补丁,将来会给您带来很多麻烦(我在开始使用 QML 时已经拥有它们,我不想再拥有它们)。对我来说,你有一个XY problem,也就是说,你要的是一个没有人保证有效的答案,而不是你的潜在问题。
  • 我认为 cmets 已经扩展了。我要说的最后一件事是,您首先要设计组件,然后再实现它们。很多时候我们都有编写代码的坏习惯,而没有清楚地了解我们想要什么(设计),请阅读What is the XY problem?bye

标签: qt qml qtquickcontrols2


【解决方案1】:

不要尝试直接访问子项。改为使用委托 ID、信号和插槽:

  • 通过GridView 的模型为所有代表提供一个“代表 ID”。
  • 在您的GridView 中,添加将用于向所有代表广播以下内容的信号:
    • 您希望其执行函数的委托的“委托 ID”。
    • AAA_Styles 函数的参数。
  • 在您的委托中,为每个AAA_Styles 函数添加一个槽。仅当广播的委托 ID 是委托的 if (broadcastedID === delegateID) { function_ab() } 时,每个插槽才会执行 AAA_Styles 函数。
  • 当您想在委托中执行function_a()function_b() 时,通过相应的GridView 信号(例如在onReleased 中)广播委托ID 和函数参数。

以下代码总结了我刚刚向您描述的内容。如果它不起作用,请将委托放在单独的 QML 文件中。这应该可以正常工作:

// Your grid
GridView {
    id: grdViewDeviceControl
    clip: true
    interactive: true
    ScrollIndicator.vertical: ScrollIndicator {}
    cellWidth: 200
    cellHeight: 300

    model: ListModel {
        /*
            Example of list element:
            ListElement { m_uuid: "{element-uuid}" }
        */
    }

    delegate: Item {
        width: grdViewDeviceControl.cellWidth
        height: grdViewDeviceControl.cellHeight

        AAA_Styles {
            id: deviceControl
            objectName: "deviceControl"
            anchors.centerIn: parent
            name: Names
            subname: Subnames
        }

        // The delegate ID
        property string delegate_id: m_uuid

        // Broadcast receivers
        function delfunc_a(uuid, argA0) {
            if (uuid === this.delegate_id) {
                deviceControl.function_a(argA0)
            }
        }

        function delfunc_b(uuid, argB0, argB1) {
            if (uuid === this.delegate_id) {
                deviceControl.function_b(argB0, argB1)
            }
        }

        // Connecting broadcasters to receivers
        Component.onCompleted: {
            grdViewDeviceControl.exec_a.connect(this.delfunc_a)
            grdViewDeviceControl.exec_b.connect(this.delfunc_b)
        }

        Component.onDestruction: {
            grdViewDeviceControl.exec_a.disconnect(this.delfunc_a)
            grdViewDeviceControl.exec_b.disconnect(this.delfunc_b)
        }
    }

    // Your broadcasters
    signal exec_a(string uuid, int argA0)
    signal exec_b(string uuid, bool argB0, string argB1)
}
// Somewhere else in your code:
onReleased: {
    /*
     * Only the delegate whose ID is "{a-given-uuid}"
     * will execute deviceControl.function_a(3):
     */
    grdViewDeviceControl.exec_a("{a-given-uuid}", 3)
    /*
     * Only the delegate whose ID is "{another-given-uuid}"
     * will execute deviceControl.function_b(true, "U got style!"):
     */
    grdViewDeviceControl.exec_b("{another-given-uuid}", true, "U got style!")
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    相关资源
    最近更新 更多