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. Optimizing Listview performance
Forum Updated to NodeBB v4.3 + New Features

Optimizing Listview performance

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 3 Posters 1.1k Views 1 Watching
  • 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.
  • M Offline
    M Offline
    MattC24
    wrote on last edited by
    #1

    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
    J.HilkJ 1 Reply Last reply
    0
    • M MattC24

      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
      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #3

      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


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      M 1 Reply Last reply
      1
      • jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote on last edited by jeremy_k
        #2

        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")
        

        Asking a question about code? http://eel.is/iso-c++/testcase/

        M 1 Reply Last reply
        0
        • M MattC24

          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
          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #3

          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


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          M 1 Reply Last reply
          1
          • J.HilkJ J.Hilk

            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

            M Offline
            M Offline
            MattC24
            wrote on last edited by
            #4

            @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!

            1 Reply Last reply
            0
            • jeremy_kJ jeremy_k

              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")
              
              M Offline
              M Offline
              MattC24
              wrote on last edited by
              #5

              @jeremy_k Thank you for your reply! I will look into DelegateChooser as well. I have also fixed that translated string issue. Was not meant to be in there!

              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