QML-如何让孩子参与其中?

时间:2019-04-04 16:01:53

标签: qt qml qtquickcontrols2

我对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()
-function_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_a function_b 但是当我使用第二个错误时出现了

  

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

那么有人可以告诉我为什么我做错了以及如何解决吗?

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

请勿尝试直接访问子项。请使用委托人ID,信号和插槽:

  • 通过您的GridView模型为所有代表提供“代表ID”。
  • 在您的GridView中,添加将用于向所有代表广播的信号:
    • 您希望其执行功能的委托人的“委托人ID”。
    • AAA_Styles函数的参数。
  • 在您的代表中,为每个AAA_Styles函数添加一个插槽。仅当广播的代表ID为代表的AAA_Styles时,每个插槽才会执行if (broadcastedID === delegateID) { function_ab() }函数。
  • 如果要在委托中执行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!")
}