【问题标题】:QML How to call method of a model from the delegateQML如何从委托中调用模型的方法
【发布时间】:2020-10-29 19:38:44
【问题描述】:

我有一个简单的 QML 程序,它有一个 ListView。 ListView 的模型和委托在单独的 QML 文件中定义。

//Main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
//import TheModel.qml
//import TheDelegate.qml


Window {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ListView {
        anchors.fill: parent
        model: theModel
        delegate: theDelegate
        focus: true

    }
    Button{
        x: 394
        y: 257
        text: "press me"
       onPressed: theModel.append({"color":"black", "cost": 5.95, "name":"Pizza"})
   }

    TheDelegate{
        id: theDelegate
    }

    TheModel{
        id:theModel
    }
}

然后是模型文件

//TheModel.qml
import QtQuick 2.0

ListModel{
    ListElement {
        color:"red";
        name: "Bill Smith"
        number: "555 3264"
    }
    ListElement {
        color:"blue";
        name: "John Brown"
        number: "555 8426"
    }
    ListElement {
        color:"green";
        name: "Sam Wise"
        number: "555 0473"
    }
}

最后是委托

    //TheDelegate.qml
    import QtQuick 2.0
    
    Component {
        Rectangle{
            color: model.color
            width: 100
            height: 100
            MouseArea{
                anchors.fill: parent
                onPressed: model.append({"color":"black", "cost": 5.95, "name":"Pizza"})
            }
        }
    }

如果我单击委托的MouseArea onPressed 方法将需要创建一个ListItem,但问题是我无法从委托访问模型的功能。令人困惑的是,这些属性是通过model 在委托中访问的。 任何人都可以指出这样做的正确方法,说如果我知道模型是ListModel 并且它有append 方法,但委托不知道,有没有办法将模型转换为已知类型那么调用一个方法呢?

【问题讨论】:

    标签: qt qml


    【解决方案1】:

    这可以通过向TheDelegate 添加一个信号来完成,您可以在theModel 可用的范围内连接该信号。我想称它为“包含的组件”,它可能有一些花哨的术语;-)

    请将TheDelegate.qml 更改为(顺便说一句,为了可重用性,我也将其更改为不是Component):

    import QtQuick 2.0
    
    Rectangle{
        color: model.color
        width: 100
        height: 100
    
        signal appendRequested(var newItem)
    
        MouseArea{
            anchors.fill: parent
            onPressed: appendRequested({"color":"black", "cost": 5.95, "name":"Pizza"})
        }
    }
    

    然后在main.qml你可以使用如下:

    ListView {
        anchors.fill: parent
        model: theModel
        delegate: theDelegate
    
        focus: true
    }
    
    Component {
        id: theDelegate
    
        TheDelegate {
            onAppendRequested: theModel.append(newItem)
        }
    }
    

    【讨论】:

    • 我明白了,这就像一个后期绑定。因为 delegate 可以单独使用,但是在 view 中使用时,视图只知道谁是模型。但是这里突然出现了一个问题。为什么“颜色:model.color”行有效?
    【解决方案2】:

    模型对象暴露给视图中的每个委托,并为该特定委托提供模型数据。和ListView的model属性不一样。

    @Amfasis 的方法很好,因为它适用于任何类型的模型和视图。

    如果您不介意将委托绑定到 ListView,可以使用附加的 ListView API:

    Component {
        Rectangle{
            id: root
            color: model.color
            width: 100
            height: 100
            MouseArea{
                anchors.fill: parent
                onPressed: root.ListView.view.model.append({"color":"black", "cost": 5.95, "name":"Pizza"})
            }
        }
    }
    

    【讨论】:

    • 您是否假设上面的 Component 与 ListView 在同一个 qml 文件中?因为我会改变 onPressed : root..... 那么根就是 Component 本身。如果是这样,那么我知道模型没有问题,因为它可以从 ListView 的 id 属性访问。
    • 这个答案是假设组件将保留在自己的文件中。
    猜你喜欢
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多