Optimizing Listview performance
-
Hello,
I'm currently working on a project (which I inherited) where I'm using a listview to display setting screens. I've been noticing long loading times of about 5-6 seconds for the screens. I also notice lag when scrolling down the listview. In this listview I have a complex delegate due to the various types of settings (toggle switches, dropdown menus, line edits, spinboxes etc.). I essentially get setting data from my c++ settingpresenter class containing what the type of setting is, min/max values , the label names of the settings, options for dropdown menus. That data is then given to my custom c++ model which is used by the listview/SettingBrowser. I'm trying to figure out what could be causing the slow down. I am somewhat new to QML and my c++ skills are average. A
lso, an important note is that I am using an embedded device to run the GUI app.
Here is my Listview code:
SettingBrowser.qml
property string name property var settingBrowserModel Rectangle { // z:5 id: title height: parent.height/6 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right color: backgroundcolor Text { id: titletext1 anchors.left: parent.left width: parent.width height: parent.height fontSizeMode: Text.Fit; text: name font.pixelSize: 20 color: textcolor verticalAlignment: Text.AlignVCenter //horizontalAlignment: Text.AlignHCenter anchors.leftMargin: parent.width/64 font.family: opensanssemibold.name textFormat : Text.PlainText } } ListView { id: settinglistView width: parent.width anchors.top: title.bottom anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter boundsBehavior: Flickable.StopAtBounds ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn active: ScrollBar.AlwaysOn } model: settingBrowserModel delegate: Rectangle{ id: settingDelegate width: settinglistView.width height: settinglistView.height/3 color: backgroundcolor Text { id: settingname anchors.left: parent.left anchors.leftMargin: parent.width/32 text: model.label //onEditingFinished: model.label = text wrapMode: Text.WordWrap color: textcolor font.pixelSize: 16 font.family: opensansregular.name height: parent.height width: parent.width *.4 verticalAlignment: TextInput.AlignVCenter textFormat : Text.PlainText } Rectangle{ id:horzSeperator height: 2 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom visible: seperator color: Variables.ultraLightGrey2 } ToggleSwitch { id: slider visible: model.type === "switch" enabled: model.type === "switch" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/4 sliderheight: parent.height*2/3 settingID: model.settingID slidervalue: { if(model.value === 0) false else true } anchors.verticalCenter: settingname.verticalCenter onModified: { settingSaved = false; slidervalue = value; model.value= slidervalue; root.sendPUDOValue(settingID,slidervalue) } } LineEdit { //z:1 id: lineedit visible: model.type === "text" enabled: model.type === "text" anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 comboheight: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter placevalue: qsTr("Text") //onModified: //textvalue: qsTr("Text") //textvalue } CustomSpinBox{ id: numedit visible: model.type === qsTr("int") enabled: model.settingEnabled //model.type === qsTr("int") anchors.right: parent.right anchors.rightMargin: parent.width/8 //32 // boxheight: parent.height //parent.height*2/3 // boxwidth: parent.width //parent.width/2 width: parent.width/2 height: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter unit: intUnit boxvalue: Qt.binding(function (){ return model.value}) //model.value minvalue: model.minValue maxvalue: model.maxValue settingID: model.settingID hover: true onModified: { settingSaved = false; boxvalue = value; model.value = boxvalue; root.sendPUDOValue(settingID,boxvalue) } } DoubleSpinBox{ //timer id: timeedit visible: model.type === "time" enabled: model.type === "time" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/2 sliderheight: parent.height*3/4 anchors.verticalCenter: settingname.verticalCenter onModified: { console.log("timer modified!") } } ComboPopUp{ //dropdown menu id: combopop //z:200 visible: model.type === qsTr("combo") enabled: model.type === qsTr("combo") anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 //rectangle width comboheight: parent.height*3/4 //rectangle height popupheight: parent_popupheight *0.5 popupwidth: parent_popupwidth * 0.9 anchors.verticalCenter: settingname.verticalCenter settingID: model.settingID comboValues: model.optionsList //property string selectedCombo: if(headerPop === "") headerPop = selectedtext; onModified: { console.log("from comboPopUp" + "settingId: " + settingID + "index: " + index); settingSaved = false; selectedtext = getSelectedText(index); root.sendTSValue(settingID, index); //console.log("selectedtext: " + selectedtext ) } } Button{ id: savebutton visible: model.type === "save" enabled: !settingSaved height: parent.height/2 width: parent.width/4 anchors.right: parent.right anchors.rightMargin: parent.width/32 anchors.verticalCenter: settingname.verticalCenter onClicked: { console.log("save button clicked!") settingSaved = true; saveClicked(); } contentItem: Text{ text: qsTr("Save") font: opensansregular.name opacity: enabled ? 1.0 : 0.3 color: Variables.black horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } } } }
I then have a presenter class that holds the data for the settings and the different lists of settings. I created a struct called settingComponent to hold this data. This data is passed through my c++ model and then to the QML page. I can show an example below.
struct settingComponent
{
Settings settingVariable;
QString type;
QString label;
QVariant value;
int minValue;
int maxValue;
int subindex;
int settingID;
QVariant optionsList;
bool settingEnabled;};
presenter.cpp
settingComponent m_s1VDO {s1VDO,settingType(s1VDO),settingLabel(s1VDO),settingValue(s1VDO), minimumValue(s1VDO),maximumValue(s1VDO),subIndex(s1VDO),settingID(s1VDO), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1VPU {s1VPU,settingType(s1VPU),settingLabel(s1VPU),settingValue(s1VPU), minimumValue(s1VPU),maximumValue(s1VPU),subIndex(s1VPU),settingID(s1VPU), optionsForSetting(s1VPU),settingEnabled(s1VPU)}; settingComponent m_s1FDO {s1FDO,settingType(s1FDO),settingLabel(s1FDO),settingValue(s1FDO), minimumValue(s1FDO),maximumValue(s1FDO),subIndex(s1FDO),settingID(s1FDO), optionsForSetting(s1FDO),settingEnabled(s1FDO)}; settingComponent m_s1FPU {s1FPU,settingType(s1FPU),settingLabel(s1FPU),settingValue(s1FPU), minimumValue(s1FPU),maximumValue(s1FPU),subIndex(s1FPU),settingID(s1FPU), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1OVSensingEnabled {s1OVSensingEnabled,settingType(s1OVSensingEnabled),settingLabel(s1OVSensingEnabled),settingValue(s1OVSensingEnabled), minimumValue(s1OVSensingEnabled),maximumValue(s1OVSensingEnabled),subIndex(s1OVSensingEnabled),settingID(s1OVSensingEnabled), optionsForSetting(s1OVSensingEnabled),settingEnabled(s1OVSensingEnabled)}; mSettingsList.append(m_s1VDO); mSettingsList.append(m_s1VPU); mSettingsList.append(m_s1FDO); mSettingsList.append(m_s1FPU); mSettingsList.append(m_s1OVSensingEnabled);
SettingScreen.qml
Page { FontLoader { id: arial source: "qrc:/fonts/arial.ttf" } FontLoader { id: arialroundhand source: "qrc:/fonts/ARLRDBD.TTF" } property int index: 0 property bool darkMode: presenter.darkMode property color backgroundcolor: darkMode ? "#131313" : Variables.white property color textcolor: darkMode ? Variables.white : Variables.anthraciteGrey property color headerBackgroundColor: darkMode ? "#2C2C2C" : Variables.ultraLightGrey2 function saveChanges() { console.log("pick up/drop settings changed") } background: Rectangle { color: backgroundcolor } Item { id: view height: parent.height anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: indicator.top SettingBrowser { id: browser height: parent.height width: parent.width name: "System Settings" intUnit: qsTr("%") settingBrowserModel: ISettingModel{ list: settingpresenter } onSaveClicked: { console.log("calling printSettingsHash()"); settingpresenter.printSettingsHash(); } onSendPUDOValue: { console.log("id: " + id + " " + "idValue: " + idvalue) ; isettingpresenter.writeSettings(id,idvalue); } } } PageIndicator { id: indicator count: view.count ``` currentIndex: view.currentIndex
anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter }
}
Problems: -Setting screen take long to load 5-6 seconds -Lag when scrolling down the full list of settings (25 in the full list) Is there a better way to implement this? Am I having the QML do too much? I understand that I am using an embedded device and I have not run QML profiler on it yet. I've only run QML Profiler on the windows version which doesn't really have any slowdown. I've also have read about the loader element. I'm not sure if that's something that could help as well. Any help/insights would be greatly appreciated! -Matt
-
Hello,
I'm currently working on a project (which I inherited) where I'm using a listview to display setting screens. I've been noticing long loading times of about 5-6 seconds for the screens. I also notice lag when scrolling down the listview. In this listview I have a complex delegate due to the various types of settings (toggle switches, dropdown menus, line edits, spinboxes etc.). I essentially get setting data from my c++ settingpresenter class containing what the type of setting is, min/max values , the label names of the settings, options for dropdown menus. That data is then given to my custom c++ model which is used by the listview/SettingBrowser. I'm trying to figure out what could be causing the slow down. I am somewhat new to QML and my c++ skills are average. A
lso, an important note is that I am using an embedded device to run the GUI app.
Here is my Listview code:
SettingBrowser.qml
property string name property var settingBrowserModel Rectangle { // z:5 id: title height: parent.height/6 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right color: backgroundcolor Text { id: titletext1 anchors.left: parent.left width: parent.width height: parent.height fontSizeMode: Text.Fit; text: name font.pixelSize: 20 color: textcolor verticalAlignment: Text.AlignVCenter //horizontalAlignment: Text.AlignHCenter anchors.leftMargin: parent.width/64 font.family: opensanssemibold.name textFormat : Text.PlainText } } ListView { id: settinglistView width: parent.width anchors.top: title.bottom anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter boundsBehavior: Flickable.StopAtBounds ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn active: ScrollBar.AlwaysOn } model: settingBrowserModel delegate: Rectangle{ id: settingDelegate width: settinglistView.width height: settinglistView.height/3 color: backgroundcolor Text { id: settingname anchors.left: parent.left anchors.leftMargin: parent.width/32 text: model.label //onEditingFinished: model.label = text wrapMode: Text.WordWrap color: textcolor font.pixelSize: 16 font.family: opensansregular.name height: parent.height width: parent.width *.4 verticalAlignment: TextInput.AlignVCenter textFormat : Text.PlainText } Rectangle{ id:horzSeperator height: 2 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom visible: seperator color: Variables.ultraLightGrey2 } ToggleSwitch { id: slider visible: model.type === "switch" enabled: model.type === "switch" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/4 sliderheight: parent.height*2/3 settingID: model.settingID slidervalue: { if(model.value === 0) false else true } anchors.verticalCenter: settingname.verticalCenter onModified: { settingSaved = false; slidervalue = value; model.value= slidervalue; root.sendPUDOValue(settingID,slidervalue) } } LineEdit { //z:1 id: lineedit visible: model.type === "text" enabled: model.type === "text" anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 comboheight: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter placevalue: qsTr("Text") //onModified: //textvalue: qsTr("Text") //textvalue } CustomSpinBox{ id: numedit visible: model.type === qsTr("int") enabled: model.settingEnabled //model.type === qsTr("int") anchors.right: parent.right anchors.rightMargin: parent.width/8 //32 // boxheight: parent.height //parent.height*2/3 // boxwidth: parent.width //parent.width/2 width: parent.width/2 height: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter unit: intUnit boxvalue: Qt.binding(function (){ return model.value}) //model.value minvalue: model.minValue maxvalue: model.maxValue settingID: model.settingID hover: true onModified: { settingSaved = false; boxvalue = value; model.value = boxvalue; root.sendPUDOValue(settingID,boxvalue) } } DoubleSpinBox{ //timer id: timeedit visible: model.type === "time" enabled: model.type === "time" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/2 sliderheight: parent.height*3/4 anchors.verticalCenter: settingname.verticalCenter onModified: { console.log("timer modified!") } } ComboPopUp{ //dropdown menu id: combopop //z:200 visible: model.type === qsTr("combo") enabled: model.type === qsTr("combo") anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 //rectangle width comboheight: parent.height*3/4 //rectangle height popupheight: parent_popupheight *0.5 popupwidth: parent_popupwidth * 0.9 anchors.verticalCenter: settingname.verticalCenter settingID: model.settingID comboValues: model.optionsList //property string selectedCombo: if(headerPop === "") headerPop = selectedtext; onModified: { console.log("from comboPopUp" + "settingId: " + settingID + "index: " + index); settingSaved = false; selectedtext = getSelectedText(index); root.sendTSValue(settingID, index); //console.log("selectedtext: " + selectedtext ) } } Button{ id: savebutton visible: model.type === "save" enabled: !settingSaved height: parent.height/2 width: parent.width/4 anchors.right: parent.right anchors.rightMargin: parent.width/32 anchors.verticalCenter: settingname.verticalCenter onClicked: { console.log("save button clicked!") settingSaved = true; saveClicked(); } contentItem: Text{ text: qsTr("Save") font: opensansregular.name opacity: enabled ? 1.0 : 0.3 color: Variables.black horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } } } }
I then have a presenter class that holds the data for the settings and the different lists of settings. I created a struct called settingComponent to hold this data. This data is passed through my c++ model and then to the QML page. I can show an example below.
struct settingComponent
{
Settings settingVariable;
QString type;
QString label;
QVariant value;
int minValue;
int maxValue;
int subindex;
int settingID;
QVariant optionsList;
bool settingEnabled;};
presenter.cpp
settingComponent m_s1VDO {s1VDO,settingType(s1VDO),settingLabel(s1VDO),settingValue(s1VDO), minimumValue(s1VDO),maximumValue(s1VDO),subIndex(s1VDO),settingID(s1VDO), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1VPU {s1VPU,settingType(s1VPU),settingLabel(s1VPU),settingValue(s1VPU), minimumValue(s1VPU),maximumValue(s1VPU),subIndex(s1VPU),settingID(s1VPU), optionsForSetting(s1VPU),settingEnabled(s1VPU)}; settingComponent m_s1FDO {s1FDO,settingType(s1FDO),settingLabel(s1FDO),settingValue(s1FDO), minimumValue(s1FDO),maximumValue(s1FDO),subIndex(s1FDO),settingID(s1FDO), optionsForSetting(s1FDO),settingEnabled(s1FDO)}; settingComponent m_s1FPU {s1FPU,settingType(s1FPU),settingLabel(s1FPU),settingValue(s1FPU), minimumValue(s1FPU),maximumValue(s1FPU),subIndex(s1FPU),settingID(s1FPU), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1OVSensingEnabled {s1OVSensingEnabled,settingType(s1OVSensingEnabled),settingLabel(s1OVSensingEnabled),settingValue(s1OVSensingEnabled), minimumValue(s1OVSensingEnabled),maximumValue(s1OVSensingEnabled),subIndex(s1OVSensingEnabled),settingID(s1OVSensingEnabled), optionsForSetting(s1OVSensingEnabled),settingEnabled(s1OVSensingEnabled)}; mSettingsList.append(m_s1VDO); mSettingsList.append(m_s1VPU); mSettingsList.append(m_s1FDO); mSettingsList.append(m_s1FPU); mSettingsList.append(m_s1OVSensingEnabled);
SettingScreen.qml
Page { FontLoader { id: arial source: "qrc:/fonts/arial.ttf" } FontLoader { id: arialroundhand source: "qrc:/fonts/ARLRDBD.TTF" } property int index: 0 property bool darkMode: presenter.darkMode property color backgroundcolor: darkMode ? "#131313" : Variables.white property color textcolor: darkMode ? Variables.white : Variables.anthraciteGrey property color headerBackgroundColor: darkMode ? "#2C2C2C" : Variables.ultraLightGrey2 function saveChanges() { console.log("pick up/drop settings changed") } background: Rectangle { color: backgroundcolor } Item { id: view height: parent.height anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: indicator.top SettingBrowser { id: browser height: parent.height width: parent.width name: "System Settings" intUnit: qsTr("%") settingBrowserModel: ISettingModel{ list: settingpresenter } onSaveClicked: { console.log("calling printSettingsHash()"); settingpresenter.printSettingsHash(); } onSendPUDOValue: { console.log("id: " + id + " " + "idValue: " + idvalue) ; isettingpresenter.writeSettings(id,idvalue); } } } PageIndicator { id: indicator count: view.count ``` currentIndex: view.currentIndex
anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter }
}
Problems: -Setting screen take long to load 5-6 seconds -Lag when scrolling down the full list of settings (25 in the full list) Is there a better way to implement this? Am I having the QML do too much? I understand that I am using an embedded device and I have not run QML profiler on it yet. I've only run QML Profiler on the windows version which doesn't really have any slowdown. I've also have read about the loader element. I'm not sure if that's something that could help as well. Any help/insights would be greatly appreciated! -Matt
hi @MattC24
a loader with asynchronous loading enabled can help you with your first problem:
Setting screen take long to load 5-6 seconds
also lazy initialization may also improve things (canFetchMore() and fetchMore())the others part
Lag when scrolling down the full list of settings (25 in the full list)
is a bit more tricky it will be effected by the above, but is in the end its probably a viewport issue. Make sure you load images and stuff asynchronous, avoid deep call chains (e.g: a.b.c.d.e.f.g.myData) avoid setting clip to true, that costs performance as well -
Using a Loader or DelegateChooser should be an easy conversion to try, and has a high probability of improving performance. The DelegateChooser example in the documentation covers exactly the situation described. It even uses the role name "type".
Some of the delegate items are attempting to use translated strings to compare to model.type, which seems like an unusual choice. For example:
CustomSpinBox{ id: numedit visible: model.type === qsTr("int")
-
Hello,
I'm currently working on a project (which I inherited) where I'm using a listview to display setting screens. I've been noticing long loading times of about 5-6 seconds for the screens. I also notice lag when scrolling down the listview. In this listview I have a complex delegate due to the various types of settings (toggle switches, dropdown menus, line edits, spinboxes etc.). I essentially get setting data from my c++ settingpresenter class containing what the type of setting is, min/max values , the label names of the settings, options for dropdown menus. That data is then given to my custom c++ model which is used by the listview/SettingBrowser. I'm trying to figure out what could be causing the slow down. I am somewhat new to QML and my c++ skills are average. A
lso, an important note is that I am using an embedded device to run the GUI app.
Here is my Listview code:
SettingBrowser.qml
property string name property var settingBrowserModel Rectangle { // z:5 id: title height: parent.height/6 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right color: backgroundcolor Text { id: titletext1 anchors.left: parent.left width: parent.width height: parent.height fontSizeMode: Text.Fit; text: name font.pixelSize: 20 color: textcolor verticalAlignment: Text.AlignVCenter //horizontalAlignment: Text.AlignHCenter anchors.leftMargin: parent.width/64 font.family: opensanssemibold.name textFormat : Text.PlainText } } ListView { id: settinglistView width: parent.width anchors.top: title.bottom anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter boundsBehavior: Flickable.StopAtBounds ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn active: ScrollBar.AlwaysOn } model: settingBrowserModel delegate: Rectangle{ id: settingDelegate width: settinglistView.width height: settinglistView.height/3 color: backgroundcolor Text { id: settingname anchors.left: parent.left anchors.leftMargin: parent.width/32 text: model.label //onEditingFinished: model.label = text wrapMode: Text.WordWrap color: textcolor font.pixelSize: 16 font.family: opensansregular.name height: parent.height width: parent.width *.4 verticalAlignment: TextInput.AlignVCenter textFormat : Text.PlainText } Rectangle{ id:horzSeperator height: 2 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom visible: seperator color: Variables.ultraLightGrey2 } ToggleSwitch { id: slider visible: model.type === "switch" enabled: model.type === "switch" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/4 sliderheight: parent.height*2/3 settingID: model.settingID slidervalue: { if(model.value === 0) false else true } anchors.verticalCenter: settingname.verticalCenter onModified: { settingSaved = false; slidervalue = value; model.value= slidervalue; root.sendPUDOValue(settingID,slidervalue) } } LineEdit { //z:1 id: lineedit visible: model.type === "text" enabled: model.type === "text" anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 comboheight: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter placevalue: qsTr("Text") //onModified: //textvalue: qsTr("Text") //textvalue } CustomSpinBox{ id: numedit visible: model.type === qsTr("int") enabled: model.settingEnabled //model.type === qsTr("int") anchors.right: parent.right anchors.rightMargin: parent.width/8 //32 // boxheight: parent.height //parent.height*2/3 // boxwidth: parent.width //parent.width/2 width: parent.width/2 height: parent.height*2/3 anchors.verticalCenter: settingname.verticalCenter unit: intUnit boxvalue: Qt.binding(function (){ return model.value}) //model.value minvalue: model.minValue maxvalue: model.maxValue settingID: model.settingID hover: true onModified: { settingSaved = false; boxvalue = value; model.value = boxvalue; root.sendPUDOValue(settingID,boxvalue) } } DoubleSpinBox{ //timer id: timeedit visible: model.type === "time" enabled: model.type === "time" anchors.right: parent.right anchors.rightMargin: parent.width/32 sliderwidth: parent.width/2 sliderheight: parent.height*3/4 anchors.verticalCenter: settingname.verticalCenter onModified: { console.log("timer modified!") } } ComboPopUp{ //dropdown menu id: combopop //z:200 visible: model.type === qsTr("combo") enabled: model.type === qsTr("combo") anchors.right: parent.right anchors.rightMargin: parent.width/32 combowidth: parent.width/2 //rectangle width comboheight: parent.height*3/4 //rectangle height popupheight: parent_popupheight *0.5 popupwidth: parent_popupwidth * 0.9 anchors.verticalCenter: settingname.verticalCenter settingID: model.settingID comboValues: model.optionsList //property string selectedCombo: if(headerPop === "") headerPop = selectedtext; onModified: { console.log("from comboPopUp" + "settingId: " + settingID + "index: " + index); settingSaved = false; selectedtext = getSelectedText(index); root.sendTSValue(settingID, index); //console.log("selectedtext: " + selectedtext ) } } Button{ id: savebutton visible: model.type === "save" enabled: !settingSaved height: parent.height/2 width: parent.width/4 anchors.right: parent.right anchors.rightMargin: parent.width/32 anchors.verticalCenter: settingname.verticalCenter onClicked: { console.log("save button clicked!") settingSaved = true; saveClicked(); } contentItem: Text{ text: qsTr("Save") font: opensansregular.name opacity: enabled ? 1.0 : 0.3 color: Variables.black horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } } } }
I then have a presenter class that holds the data for the settings and the different lists of settings. I created a struct called settingComponent to hold this data. This data is passed through my c++ model and then to the QML page. I can show an example below.
struct settingComponent
{
Settings settingVariable;
QString type;
QString label;
QVariant value;
int minValue;
int maxValue;
int subindex;
int settingID;
QVariant optionsList;
bool settingEnabled;};
presenter.cpp
settingComponent m_s1VDO {s1VDO,settingType(s1VDO),settingLabel(s1VDO),settingValue(s1VDO), minimumValue(s1VDO),maximumValue(s1VDO),subIndex(s1VDO),settingID(s1VDO), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1VPU {s1VPU,settingType(s1VPU),settingLabel(s1VPU),settingValue(s1VPU), minimumValue(s1VPU),maximumValue(s1VPU),subIndex(s1VPU),settingID(s1VPU), optionsForSetting(s1VPU),settingEnabled(s1VPU)}; settingComponent m_s1FDO {s1FDO,settingType(s1FDO),settingLabel(s1FDO),settingValue(s1FDO), minimumValue(s1FDO),maximumValue(s1FDO),subIndex(s1FDO),settingID(s1FDO), optionsForSetting(s1FDO),settingEnabled(s1FDO)}; settingComponent m_s1FPU {s1FPU,settingType(s1FPU),settingLabel(s1FPU),settingValue(s1FPU), minimumValue(s1FPU),maximumValue(s1FPU),subIndex(s1FPU),settingID(s1FPU), optionsForSetting(s1VDO),settingEnabled(s1VDO)}; settingComponent m_s1OVSensingEnabled {s1OVSensingEnabled,settingType(s1OVSensingEnabled),settingLabel(s1OVSensingEnabled),settingValue(s1OVSensingEnabled), minimumValue(s1OVSensingEnabled),maximumValue(s1OVSensingEnabled),subIndex(s1OVSensingEnabled),settingID(s1OVSensingEnabled), optionsForSetting(s1OVSensingEnabled),settingEnabled(s1OVSensingEnabled)}; mSettingsList.append(m_s1VDO); mSettingsList.append(m_s1VPU); mSettingsList.append(m_s1FDO); mSettingsList.append(m_s1FPU); mSettingsList.append(m_s1OVSensingEnabled);
SettingScreen.qml
Page { FontLoader { id: arial source: "qrc:/fonts/arial.ttf" } FontLoader { id: arialroundhand source: "qrc:/fonts/ARLRDBD.TTF" } property int index: 0 property bool darkMode: presenter.darkMode property color backgroundcolor: darkMode ? "#131313" : Variables.white property color textcolor: darkMode ? Variables.white : Variables.anthraciteGrey property color headerBackgroundColor: darkMode ? "#2C2C2C" : Variables.ultraLightGrey2 function saveChanges() { console.log("pick up/drop settings changed") } background: Rectangle { color: backgroundcolor } Item { id: view height: parent.height anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: indicator.top SettingBrowser { id: browser height: parent.height width: parent.width name: "System Settings" intUnit: qsTr("%") settingBrowserModel: ISettingModel{ list: settingpresenter } onSaveClicked: { console.log("calling printSettingsHash()"); settingpresenter.printSettingsHash(); } onSendPUDOValue: { console.log("id: " + id + " " + "idValue: " + idvalue) ; isettingpresenter.writeSettings(id,idvalue); } } } PageIndicator { id: indicator count: view.count ``` currentIndex: view.currentIndex
anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter }
}
Problems: -Setting screen take long to load 5-6 seconds -Lag when scrolling down the full list of settings (25 in the full list) Is there a better way to implement this? Am I having the QML do too much? I understand that I am using an embedded device and I have not run QML profiler on it yet. I've only run QML Profiler on the windows version which doesn't really have any slowdown. I've also have read about the loader element. I'm not sure if that's something that could help as well. Any help/insights would be greatly appreciated! -Matt
hi @MattC24
a loader with asynchronous loading enabled can help you with your first problem:
Setting screen take long to load 5-6 seconds
also lazy initialization may also improve things (canFetchMore() and fetchMore())the others part
Lag when scrolling down the full list of settings (25 in the full list)
is a bit more tricky it will be effected by the above, but is in the end its probably a viewport issue. Make sure you load images and stuff asynchronous, avoid deep call chains (e.g: a.b.c.d.e.f.g.myData) avoid setting clip to true, that costs performance as well -
hi @MattC24
a loader with asynchronous loading enabled can help you with your first problem:
Setting screen take long to load 5-6 seconds
also lazy initialization may also improve things (canFetchMore() and fetchMore())the others part
Lag when scrolling down the full list of settings (25 in the full list)
is a bit more tricky it will be effected by the above, but is in the end its probably a viewport issue. Make sure you load images and stuff asynchronous, avoid deep call chains (e.g: a.b.c.d.e.f.g.myData) avoid setting clip to true, that costs performance as well@J-Hilk Thank you for your response! I'll look into how to use loader element. Should the loader element be applied to the individual setting components (CustomSpinBox,ToggleSwitch etc.) or the overall listview(SettingBrowser.qml)? I'm not super familiar with how to use it.
I'll look into your suggestions for the second problem as well!
-
Using a Loader or DelegateChooser should be an easy conversion to try, and has a high probability of improving performance. The DelegateChooser example in the documentation covers exactly the situation described. It even uses the role name "type".
Some of the delegate items are attempting to use translated strings to compare to model.type, which seems like an unusual choice. For example:
CustomSpinBox{ id: numedit visible: model.type === qsTr("int")