Qml c++ 不同的委托 qt mvc

Posted

技术标签:

【中文标题】Qml c++ 不同的委托 qt mvc【英文标题】:Qml c++ diffrent delegates qt mvc 【发布时间】:2021-10-23 05:39:01 【问题描述】:

如何在 qml 中为 ListView 使用不同的委托。例如,我有 QList 列表,SomeObject 有两个字段:类型(圆形、矩形等)和 someValue。我为此列表创建了 QListModel。我有不同的 qml 元素(circle.qml、rectangle.qml 等)。如何按类型查看项目的委托,并在此委托中查看字段 someValue。我可以在没有表格/列表的情况下定位这些代表吗?我想通过坐标(x,y)来定位它们。

【问题讨论】:

是的,可能。检查 QML 中名为 Repeater 的项目,它可能会有所帮助。并且要将基于 QObject 的实例公开给 QML,您必须使用基于 QAbstractItemModel 的列表模型,在这种情况下直接使用 QList 将无济于事。 我正在使用 QAbstractListModel。我在 qml 中得到类型和值。我如何使用中继器,按类型选择委托?谢谢。 【参考方案1】:

要根据角色有不同的委托(也可以根据行或列来完成),您应该使用DelegateChooserDelegateChoice

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import Qt.labs.qmlmodels 1.0

Window 
    width: 640
    height: 480
    visible: true

    ListModel 
        id: shapeModel
        ListElement 
            type: "circle"
            value: 100
            x: 10
            y: 10
        
        ListElement 
            type: "rectangle"
            value: 30
            x: 100
            y: 100
        
        ListElement 
            type: "circle"
            value: 30
            x: 300
            y: 450
        
        ListElement 
            type: "rectangle"
            value: 20
            x: 500
            y: 200
        
        ListElement 
            type: "circle"
            value: 25
            x: 650
            y: 100
        
        ListElement 
            type: "rectangle"
            value: 60
            x: 600
            y: 200
        
    

    Flickable 
        anchors.fill: parent
        contentWidth: contentItem.childrenRect.width
        contentHeight: contentItem.childrenRect.height
        Repeater 
            model: shapeModel
            delegate: DelegateChooser 
                role: "type"
                DelegateChoice 
                    roleValue: "rectangle"
                    Rectangle 
                        x: model.x
                        y: model.y
                        height: model.value
                        width: model.value
                        border.color: "orange"
                        border.width: 1
                    
                
                DelegateChoice 
                    roleValue: "circle"
                    Rectangle 
                        x: model.x
                        y: model.y
                        height: model.value
                        width: model.value
                        radius: model.value/2
                        border.color: "blue"
                        border.width: 1
                    
                
            
        
    

它避免了加载器的额外间接。

【讨论】:

很好,我遇到的新事物。我会在我未来的项目中尝试这个。【参考方案2】:
    您可以尝试一个可能符合您要求的 qml Loader 概念。基本上,您不能为单个视图定义多个委托。因此,将您的 Top Delegate 设置为加载器并根据类型加载项目将有助于您解决这种情况。 定位也是可能的,您可以使用模型数据定义 x 和 y 位置。这样您就可以相应地对齐视图项目。在这种情况下,我使用了 Scrollview + Repeater

在这里分享了一个最小的样本。为简单起见,我将数据保存在 Qml ListModel 中。对来自 c++ 模型的对象也可以这样做。 Here 也提供了作为 Qt 解决方案项目的源代码。

// ShapeModel.qml //
import QtQuick 2.15
import QtQml.Models 2.15

ListModel 
    ListElement 
        type: "circle"
        val: "100"
        xpos: 10
        ypos: 10
    
    ListElement 
        type: "rectangle"
        val: "30"
        xpos: 100
        ypos: 100
    
    ListElement 
        type: "circle"
        val: "150"
        xpos: 300
        ypos: 450
    
    ListElement 
        type: "rectangle"
        val: "20"
        xpos: 500
        ypos: 200
    
    ListElement 
        type: "circle"
        val: "25"
        xpos: 650
        ypos: 100
    
    ListElement 
        type: "rectangle"
        val: "60"
        xpos: 600
        ypos: 200
    

// main.qml //
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window 
    width: 640
    height: 480
    visible: true
    title: qsTr("Qt MVC")

    Component 
        id: componentCircleId
        Rectangle 
            border.color: "blue"
            border.width: 1
            height: value
            width: value
            radius: value/2
        
    
    Component 
        id: componentRectangleId
        Rectangle 
            border.color: "orange"
            border.width: 1
            height: value
            width: value
        
    

    Component 
        id: componentLoaderId
        Loader 
            property real value: val
            x: xpos
            y: ypos
            sourceComponent: type === "circle" ?
                                 componentCircleId : componentRectangleId
        
    

    ScrollView 
        id: scrollviewId
        anchors.fill: parent
        Repeater 
            anchors.fill: parent
            model: ShapeModel
            delegate: componentLoaderId
            onItemAdded: 
                // scroll area computation
                // Better solutions may be available
                if(item.x+item.width > scrollviewId.contentWidth)
                    scrollviewId.contentWidth = item.x+item.width
                if(item.y+item.height > scrollviewId.contentHeight)
                    scrollviewId.contentHeight = item.y+item.height
            
        
    


【讨论】:

以上是关于Qml c++ 不同的委托 qt mvc的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 更改 QML Listview 委托

Qt QML包含来自不同目录的问题

Qt中使用QML和Listview的问题

如何检索 QML 相机提要并发送到 C++ 后端

如何从 C++ 访问 QML ListView 委托项目?

Qt C++: 怎样在两个MainWindow或者Widget之间交换数据