Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. ListView with Flow layout
Forum Updated to NodeBB v4.3 + New Features

ListView with Flow layout

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qmllistviewlayout
3 Posts 2 Posters 235 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alouette
    wrote last edited by
    #1

    My question is similar to this question, but it still not answered. I need a view for displaying items from C++ model with such features:

    • This view has fixed width and height;
    • Fixed width of each item;
    • Dynamically adjusted item's height according to it's content;
    • Items are laid out by columns;
    • View has horizontal scroll.

    It must look like this:

    MulticolumnListView.jpg

    What I've tried?

    1. Manually calculate item's position:
    delegate: Item {
        x: 200
        y: 30
    }
    

    but it has no effect.

    1. Manually compose a view with ScrollView, Flow, Repeater. Using these types, the items can be laid out as needed, but this approach has a number of problems. ListView doesn't load and render any invisible items, but Repeater are. ListView provides attached property but Repeater are not.

    So, what is the best approach for compose such layout?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SuhasKrishanamurthy
      wrote last edited by
      #2

      The layout you're describing — where items have a fixed width, dynamic height, are laid out vertically in columns, and the view scrolls horizontally — can be implemented in QML using a GridView with a few key settings:

      Use flow: GridView.FlowTopToBottom to lay out items vertically in each column.
      Set orientation: Qt.Horizontal to enable horizontal scrolling.
      Define cellWidth to control the fixed width of each item.
      Let each item calculate its own height dynamically by using implicitHeight based on its content (e.g., a Text element with wrapMode).
      Use a GridView instead of Repeater + Flow so that off-screen items are not created unnecessarily

      GridView {
          id: gridView
          width: 600
          height: 400
          cellWidth: 200 
          cellHeight: 100 
          flow: GridView.FlowTopToBottom
          model: myCppModel
          orientation: Qt.Horizontal 
          boundsBehavior: Flickable.StopAtBounds
          clip: true
      
          delegate: Item {
              width: gridView.cellWidth
              height: contentItem.implicitHeight 
      
              Rectangle {
                  id: contentItem
                  width: parent.width
                  color: "lightgray"
                  implicitHeight: text.implicitHeight + 20
      
                  Text {
                      id: text
                      text: model.display
                      wrapMode: Text.WordWrap
                      anchors.margins: 10
                      anchors.fill: parent
                  }
              }
          }
      }
      
      
      1 Reply Last reply
      0
      • A Offline
        A Offline
        Alouette
        wrote last edited by Alouette
        #3

        @SuhasKrishanamurthy, thanks for your help, but the GridView component has fixed cell's width and height. Items' height can grow up, but if it will be greater than cell's size, the collision occures. If I adjusted GridView's cell size depending on size of largest item, there were too much free space between small items. The following code lays items out with collision:

        GridView {
            id: gridView
            width: 600
            height: 400
            cellWidth: 200
            cellHeight: 100
            flow: GridView.FlowTopToBottom
        
            model: ListModel {
                ListElement {
                    value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
                ListElement {
                    value: "Lorem ipsum dolor sit amet"
                }
            }
        
            // orientation: Qt.Horizontal // GridView doesn't have this property
            boundsBehavior: Flickable.StopAtBounds
            clip: true
        
            delegate: Item {
                width: gridView.cellWidth
                height: contentItem.implicitHeight
                required property string value
                Rectangle {
                    id: contentItem
                    width: parent.width
                    color: "lightgray"
                    implicitHeight: tex.implicitHeight + 20
        
                    Text {
                        id: tex
                        text: value
                        wrapMode: Text.WordWrap
                        anchors.margins: 10
                        anchors.fill: parent
                    }
                }
            }
        }
        

        屏幕截图 2025-05-20 132621.png

        The desired behavior is lay items out onto the first column until it has free space and then turn into the next column (see picture in the question). Unfortunately, GridView lays item out strictly as a grid.

        This is partially implemented with Flow + Repeater layout:

        屏幕截图 2025-05-20 134148.png

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved