Mohan S
Mohan S

Reputation: 11

A Repeater using Javascript array model creates performance Issues in Qt 5.12

I'm using:

I am facing some performance issues because the repeater uses the JavaScript array model, then whenever any item have changes, the whole model is reset and the repeater redraws all items.

Same issue in: Repeater model very slow when copying an item

My same project code is flashed in updated Processor version IMX 8 target device and also updated Qt version 6.4. In this device, I couldn't see this performance issue.

So, If I update my Qt version from 5.12 to 6.4 in IMX 587 processor target device, does this performance issue get resolved?

Since then, I tried to change old code that is a big and complex one.

I also tried modifying my code to use List model:

ListModel { id:listModel }

function handleModelChanged() {
    delegateModel.model = areaViewModel;
    const newUiType = areaViewModel.uiType;

    if (newUiType !== uiType || !modelDataIsEqual(delegateModel, listModel) ) { 
        listModel.clear();
        dlaButtonStyle = areaModel.combineBtnStyle;
        oddEvenBtnAppearance = areaModel.getLockedButtonAppearance();

        for (var row = 0; row < delegateModel.model.rowCount(); row++) {
            var item = delegateModel.items.get(row).model;
            var button = dataModelItemToButton(item);                 
            listModel.append(button);
        } 
        
        console.log(listModel.get(0).dataAreaName);
        uiType = newUiType;
    } else {
        console.log("GRID buttons are same");
    }
}

Repeater {
    id: areaRepeater
    model: listModel

    delegate: {
        gridButton;
    }

    onItemAdded: {              
        if (index == areaRepeater.count - 1) {
            console.log("GRID repeater added " + areaRepeater.count + " buttons")
            updateItems()
        }
    }
}
}

But, I got this output when exposing this ListModel in Repeater:

when repeater model changed to list model

But our expected result is:

without changing old code

I thought item properties are not set properly in the delegate.

Where have I made a mistake in my code and how do I resolve it?

Upvotes: 0

Views: 234

Answers (2)

Mohan S
Mohan S

Reputation: 11

Stephen Quan Thanks for your answer. As per your suggestion modified my code to List model.

ListModel{
id:listModel
}

function handleModelChanged() {
    delegateModel.model = areaViewModel;
    const newUiType = areaViewModel.uiType
    if (newUiType !== uiType || !modelDataIsEqual(delegateModel, listModel) ) { 
        listModel.clear()
        dlaButtonStyle = areaModel.combineBtnStyle
        oddEvenBtnAppearance = areaModel.getLockedButtonAppearance()

        for (var row = 0; row < delegateModel.model.rowCount(); row++) {
            var item = delegateModel.items.get(row).model;
            var button = dataModelItemToButton(item);                 
            listModel.append(button);
        } 
        
        console.log(listModel.get(0).dataAreaName)
        uiType = newUiType 
        
    } else {
        console.log("GRID buttons are same")
    }
}

 Repeater 
{
    id: areaRepeater
    model: listModel

    delegate: {
            gridButton;
        }
    onItemAdded: {              
        if (index == areaRepeater.count - 1) {
            console.log("GRID repeater added " + areaRepeater.count + " buttons")
            updateItems()
            }
        }
    }
}

But, I got this output when expose this listmodel in repeater. when repeater model changed to list model - Image But our expected result is without changing old code - Image

I thought item properties not set properly in delegate.
Where I made mistake in my code. Kindly, help to resolve it.

Upvotes: 0

Stephen Quan
Stephen Quan

Reputation: 26299

The following QML demonstrates 3 different ways to set and update the model in your Repeater

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    id: page
    property var dataModel: []
    property list<var> dataList: []
    ListModel { id: dataListModel }
    ColumnLayout {
        Repeater {
            id: repeater
            model: dataModel
            delegate: Label { text: modelData.txt }
        }
        Repeater {
            model: dataList
            delegate: Label { text: modelData.txt }
        }
        Repeater {
            model: dataListModel
            delegate: Label { text: txt }
        }
    }
    function dataModel_add(data) {
        dataModel.push( data );
        repeater.model = dataModel; // inefficient
        dataList.push( data );
        dataListModel.append( data );
    }
    Component.onCompleted: {
        dataModel_add( { "txt" : "Hello" } );
        dataModel_add( { "txt" : "World" } );
    }
}

The first method, dataModel uses straight Javascript, and, no change detection occurs, so, we have to repeatedly update repeater.model to see the changes, hence the inefficiency.

The second and third methods, list<var> and ListModel respectively, both have change detection, so, the Repeater model can be set declarative and will react to subsequent push / append.

In short, don't expect upgrading to Qt6.4 will solve your problem. You will need to do code changes to switch away from your Javascript model.

Upvotes: 1

Related Questions