bardao
bardao

Reputation: 954

QML solution for a structured layout not using a GridView or ListView but using a c++ model

I am trying to think of a way to represent some items in a very structured way by using Row and Column only. I got the idea from Qt Widgets where you can do everything with Horizontal and Vertical layouts and have a beautiful UI. The issue is that I still want the data that is creating my QML items to come from c++, which entails a model of some sort. From what I know models can be only bound to PathView, GridView or ListView. Also that data will change dynamically based on some "add" and "remove" operations signaled by the QML UI. Is there a way to use Row and Column with a model?

Upvotes: 0

Views: 220

Answers (1)

derM
derM

Reputation: 13711

Let us assume your model shall populate a Grid, a Row and a Column:

ListModel {
    id: lm
    ListElement { target: "Grid"; content: "green" }
    ListElement { target: "Grid"; content: "blue" }
    ListElement { target: "Grid"; content: "yellow" }
    ListElement { target: "Grid"; content: "orange" }
    ListElement { target: "Row"; content: "green" }
    ListElement { target: "Row"; content: "blue" }
    ListElement { target: "Row"; content: "yellow" }
    ListElement { target: "Row"; content: "orange" }
    ListElement { target: "Column"; content: "green" }
    ListElement { target: "Column"; content: "blue" }
    ListElement { target: "Column"; content: "yellow" }
    ListElement { target: "Column"; content: "orange" }
}

Row {
    id: row
    spacing: 2
    anchors {
        top: parent.top
        left: parent.left
        right: parent.right
    }
}
Column {
    id: column
    spacing: 2
    anchors {
        top: row.bottom; topMargin: 2
        left: parent.left
        bottom: parent.bottom
    }
}
Grid {
    id: grid
    spacing: 2
    columns: 2
    anchors {
        top: row.bottom
        left: column.right
        right: parent.right
        bottom: parent.bottom
        margins: 102
    }
}

You can either use a Repeater like this:

Repeater {
    model: lm
    delegate:  Rectangle {
        width: 100
        height: 100
        parent: (target === "Grid" ? grid :
                   (target === "Row" ? row :
                      (target === "Column" ? column :
                         null)))
        color: content
    }
}

which may give you an warning:

QQuickItem::stackAfter: Cannot stack after 0x3d5cb18, which must be a sibling

Or you can use the Instantiator, which will need to create an additional QtObject but instead you won't get any warning.

Instantiator {
    model: lm
    delegate: QtObject {
        property Item child: Rectangle {
        width: 100
        height: 100
        parent: (target === "Grid" ? grid :
                   (target === "Row" ? row :
                      (target === "Column" ? column :
                         null)))
        color: content
    }}
}

And you can even have multiple objects for one model entry...

Instantiator {
    model: lm
    delegate: QtObject {
        property Item child1: Rectangle {
        width: 100
        height: 100
        parent: (target === "Row" ? row :
                   (target === "Column" ? column :
                      null)) // If "Grid" this thing will be created but not shown.
        color: content
        }

        property Item gridItem: Button {
            width: 100
            height: 30
            text: content
            onClicked: rootWin.color = content
            parent: grid
        }
    }
}

Upvotes: 1

Related Questions