0

I am trying to position a largish number (5k - 10k elements) of rectangles in a Flickable. The data comes from a custom model, a subclass of QAbstractListModel. The expected outcome looks like this:

enter image description here

My first approach was to use a Repeater with a delegate to create the rectangles like this:

Repeater {
    id: repeater
    model: particleListModel
    delegate: mapDelegate
}

Component {
    id: mapDelegate

Rectangle {
    property bool checked: false
    id: particle
    color: "transparent"
    width: model.boundswidth
    height: model.boundsheight
    x: model.boundsx
    y: model.boundsy
    MouseArea {
        id: mouseArea
        anchors.fill: parent
        hoverEnabled: true
        onClicked: {
            console.log(model.index)
            particleIndex = model.index
        }
    }
    border.color: mouseArea.containsMouse ? "lightgreen" : (model.index === particleIndex) ? "green" : "red"
    border.width: 1.5
    }
}

This works fine to display the rectangles, however it takes a good while to load (~6 seconds) and blocks the UI while it does so. Therefore my seconds approach was to use a Loader to populate the map asynchronously like so:

Component {
    id: mapDelegate

    Loader {
        id: particle
        asynchronous: true
        onLoaded: {
            console.log("loaded " + model.index)
        }

        sourceComponent:
            Rectangle {
                property bool checked: false
                color: "red"
                width: model.boundswidth
                height: model.boundsheight
                x: model.boundsx
                y: model.boundsy
                MouseArea {
                    id: mouseArea
                    anchors.fill: parent
                    hoverEnabled: true
                    onClicked: {
                        console.log(model.index)
                        particleIndex = model.index
                    }
                }
                border.color: mouseArea.containsMouse ? "lightgreen" : (model.index === particleIndex) ? "green" : "red"
                border.width: 1.5
            }
        }
    }

While this works and does not block the UI it takes a long time to finish loading all the elements (~25 seconds). The first few elements load very quickly but the loading gets more and more sluggish towards the end, slowing down to a point where you can watch single elements being added.

I would like to increase the performance to load all elements within a reasonable time while not blocking the UI. Is there another way I am missing? Or is there an elegant way to only load the elements needed in the current view? What would be the right approach to take here?

Herr von Wurst
  • 2,571
  • 5
  • 32
  • 53

1 Answers1

2

If you are dealing with large amount of data there are few techniques that you can take leverage of.

  1. Load data in the background first like using webworker and then passing processed output to view. Avoid manipulating view itself.
  2. Try loading in chunks or elements only currently in view.

The idea here is to load the initial screen quickly and then do rest of the processing in the background and adding elements to it. If you try to put all 10k elements at once, it will not produce desirable results.

Prioritize your data and view to the minimal during the first load and then operate.