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. QML and comboBox inside TableView

QML and comboBox inside TableView

Scheduled Pinned Locked Moved Solved QML and Qt Quick
8 Posts 3 Posters 2.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    g0ku_0ne
    wrote on last edited by
    #1

    I'm trying to design a mobile application using QT 5.12 with comboBox inside TableView. This code is simplified and extract from the real application, and reproduces the issue :

    import QtQuick 2.9
    import QtQuick.Controls 2.2
    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.0
    import QtQuick.Controls 1.2
    import QtQuick.Window 2.0
    import QtQuick.Controls.Styles 1.2
    
    ApplicationWindow {
    
        visible: true
        width: 640
        height: 480
        title: qsTr("Scroll")
    
        Component.onCompleted: {
            var i=0;
            for(;i<50;i++)
            {
                console.log("ApplicationWindow.onCompleted");
    
                var myBoject = {"text":"Banana"};
                idListModelForFlightToExport.append(myBoject);
            }
    
        }
    
        ListModel {
            id: idListModelForFlightToExport
        }
    
        Component  {
            id: checkBoxDelegate
            ComboBox {
                anchors.fill: parent;
                model: [ {"text":"Banana"}, {"text":"Apple"}, {"text":"Coconut"} ]
                textRole: "text";
                Component.onCompleted: {
                    console.log("checkBoxDelegate.onCompleted");
                }
            }
        }
    
        TableView {
            id: idTableViewFlightsToExport
    
            sortIndicatorVisible: false
    
            model: idListModelForFlightToExport
            anchors.fill: parent
            TableViewColumn {
                id: isExportedColumn
                title: qsTr("Column")
                movable: false
                resizable: false
                delegate:checkBoxDelegate
            }
        }
    }
    

    But when I change the value of a comboBox, and then I scroll down with finger, some others comboBox change their value.

    i.e if I change the first combo, and I scroll, the value of the first combo will be display on another combo (which seems randomly choosen) and the first combo seems to be reset. If I scroll once again, another combo change value.

    I already tried with QT 5.14, same result.

    Here is video demonstarting the issue : streamable.com/in6nh

    This code is pretty simple, but I must do something wrong because it seems that nobody faced this issue...

    Thanks

    1 Reply Last reply
    0
    • G Offline
      G Offline
      g0ku_0ne
      wrote on last edited by
      #8

      Hi all,

      I resume here all problems I faced :

      First I developped my application with QT 5.12.6. The original issue is the display value of combobox (contained in a TableView) which randomly changed on hidden combo after scrolling back. Video : streamable.com/in6nh

      Thanks to @6thC, I understand that the delegate of hidden combobox is reused for shown combobox, this is a new behavior described here : https://www.qt.io/blog/2018/08/29/tableview.

      But in my original case, I used TableView with TableViewColumn, which is the old version. (import QtQuick 2.12 import QtQuick.Controls 1.4)
      So why am I impacted by this new behavior ? This is a good question, and I don't know the answer. If someone has a clue ...

      Anyway, I'm stuck with a TableView 1.0, which has the "reuse" behavior BUT which do not provide TableView.onPooled and TableView.onReused signals... So from my point of view, this is a bug and I have to use the new TableView.

      So I change my code to use the full TableView 2.0, still in 5.12.6 : I replace "import QtQuick.Controls 1.4" by "import QtQuick.Controls 2.5". TableViewColumn is no more accessible, so columns can no more be defined in qml because : 
      "A TableView displays data from models created from built-in QML types such as ListModel and XmlListModel, which populates the first column only in a TableView. To create models with multiple columns, create a model in C++ that inherits QAbstractItemModel, and expose it to QML."Extract from : https://doc.qt.io/qt-5.12/qml-qtquick-tableview.html  
      Arg !!! In QT 5.14, there is a TableModel which allow you the colums definition in qml file : https://doc-snapshots.qt.io/qt5-5.14/qml-qt-labs-qmlmodels-tablemodel.html
      But I prefere to not migrate my project on QT 5.14, because it's quite a big project, and each migration comes with new errors to fix... So, ok, let's implement a model in C++, I the model here : took https://doc.qt.io/qt-5.12/qml-qtquick-tableview.html. Now I can define the number of column I want. Great !
      On Qml side, I implement a combobox delegate, with a simple static model, with reuseItems enable : Still not working. As soon as a delegate is pool/reuse while scrolling, the display value does'nt match with the expected one, even I don't change anything, It's full random.

      So I tried to implement "TableView.onReused" : Each time "onReused" is called, I look into an array (filled with callback "onActivated" of the combo, to store the selected index.) the correct index. The table seems to be well filled, but display is still random. That's boring.

      So I tried to disable "reuse" mechanism, and initialize on the onCompleted of combo delegate  the correct index, stored in the array.

      FANTASTIC, it finally works !!!! OMG so many steps to just display combo in a table ...

      Just below is the code I use, not just a sentence, not just some parts : ALL THE CODE. Maybe it's not the best code to do what I want to do, but it works ! If you want other component than combobox in your delegate of TableView, I tested to create a CheckBox, and It seems to well work. But I don't implement the array to store the values. It's the same mechanism than the combobox.

      If someone find a way to do the same think with "reuse" mechanism enable, I take.

      Thanks for your patience,

      G0ku

      There are 5 files :
      1/ main.qml
      2/ CheckBox.qml
      3/ ComboBox.qml
      4/ tableViewModelExportGivav.h
      5/ tableViewModelExportGivav.cpp

      1/ main.qml

      import QtQuick 2.12
      import QtQuick.Controls 2.5
      // Dummy model, required to create more than one column
      import TableViewModelExportGivav 0.1
      
      ApplicationWindow {
          id: idAppWindow
      
          visible: true
          width: 640
          height: 480
      
          title: qsTr("Scroll test")
      
          // Component created in the delegate of the TableView
          property variant myComponent;
      
          // Array which store the selected index of all the combobox of the TableView
          property variant tabIndexComboBox : [];
      
          // Retrieve the data position on the list tabIndexComboBox
          function findPosInArray(iRow, iColumn)
          {
              var posToReturn = -1;
      
              for(var i=0; i<tabIndexComboBox.length;i++)
              {
                  var indexObjectExisting = tabIndexComboBox[i];
      
                  if( (indexObjectExisting._row===iRow) && (indexObjectExisting._column===iColumn) )
                  {
                      posToReturn = i;
                      break;
                  }
              }
      
              console.log("findPosInArray : called with iRow=" + iRow + " and iColumn=" + iColumn + ", returned index=" + posToReturn);
      
              return posToReturn;
          }
      
          // Add data position on the list tabIndexComboBox
          function manageIndex(iRow, iColumn, iIndex) {
              var indexObject = {};
              indexObject._row = iRow;
              indexObject._column = iColumn;
              indexObject._selectedIndex = iIndex;
      
              var indexCb = findPosInArray(iRow, iColumn);
              if(-1 === indexCb)
              {
                  tabIndexComboBox.push(indexObject);
                  console.log("manageIndex : object non trouve et ajoute index=" + iIndex);
              }
              else
              {
                  tabIndexComboBox[indexCb] = indexObject;
                  console.log("manageIndex : object trouve et MAJ index=" + iIndex);
              }
      
              console.log("manageIndex.length : " + tabIndexComboBox.length);
          }
      
          // Retrieve selected index of the combobox
          function retrieveIndex(iRow, iColumn) {
              var indexToRetrieve = -1;
              var indexCb = findPosInArray(iRow, iColumn);
      
              if(-1 !== indexCb)
                  indexToRetrieve = tabIndexComboBox[indexCb]._selectedIndex;
      
              return indexToRetrieve;
          }
      
          Component  {
              id: idTableViewDelegate
      
              Rectangle {
                  id:idRect
                  implicitWidth: 150
                  implicitHeight: 50
      
                  Component.onCompleted: {
                      if(column === 0)
                      {
                          myComponent = Qt.createComponent("qrc:///CheckBox.qml");
                      }
                      else if(column === 1)
                      {
                          myComponent = Qt.createComponent("qrc:///ComboBox.qml");
                      }
      
                      if (myComponent.status === Component.Ready)
                      {
                         //console.log("myComponent is ready");
                         myComponent.createObject(idRect, {x: idRect.x, y: idRect.y});
                      }
                      else
                      {
                          //console.log("myComponent is NOT ready");
                          myComponent.statusChanged.connect(finishCreationComponent);
                      }
                  }
      
                  TableView.onReused: {
                      console.log("TableView.onReused : AIE AIE AIE");
                  }
              }
          }
      
          function finishCreationComponent(iStatus) {
              // Not required
          }
      
          Row{
              id:idRow
              Button {
                  id:idButtonDump
                  text:"Dump"
                  onPressed: {
                      console.log("DUMP START tabIndexComboBox");
                      for(var i=0; i<tabIndexComboBox.length;i++)
                      {
                          var indexObjectExisting = tabIndexComboBox[i];
      
                          console.log("tabIndexComboBox i=" + i + ", value=" + JSON.stringify(indexObjectExisting));
                      }
                      console.log("DUMP STOP tabIndexComboBox");
                  }
              }
      
      
              Button {
                  id:idButtonClear
                  text:"Clear"
                  onPressed: {
                      tabIndexComboBox = [];
                  }
              }
          }
      
          TableView {
              id:idTableView
      
              anchors.top:idRow.bottom
              anchors.bottom:parent.bottom
              anchors.right:parent.right
              anchors.left:parent.left
      
              model : TableViewModelExportGivav {
      
              }
      
              delegate: idTableViewDelegate;
      
              reuseItems:false
          }
      }
      

      2/ CheckBox.qml

      import QtQuick 2.12
      import QtQuick.Controls 2.5
      
      Rectangle {
          CheckBox {
              id: idCheckBoxDelegate
      
              Component.onCompleted: {
                  console.log("idCheckBoxDelegate.onCompleted");
              }
      
          }
      }
      

      3/ ComboBox.qml

      import QtQuick 2.12
      import QtQuick.Controls 2.5
      
      Rectangle {
      
          ComboBox {
              id: idComboBoxDelegate
      
              model: [ {"text":"Banana"}, {"text":"Apple"}, {"text":"Coconut"} ]
              textRole: "text";
      
              Component.onCompleted: {
                  console.log("idComboBoxDelegate.onCompleted for row=" + row);
      
                  currentIndex = idAppWindow.retrieveIndex(row, column);
              }
      
              //currentIndex: idAppWindow.retrieveIndex(row, column);
      
              onActivated: {
                  console.log("checkBoxDelegate.onCurrentIndexChanged : row=" + row + ", column=" + column + ", value set to : " + index);
      
                  idAppWindow.manageIndex(row, column, index);
              }
          }
      }
      

      4/ tableViewModelExportGivav.h

      #ifndef TableViewModelExportGivav_H
      #define TableViewModelExportGivav_H
      
      #include <QObject>
      #include <QAbstractTableModel>
      
      class TableViewModelExportGivav : public QAbstractTableModel
      {
          Q_OBJECT
      
      public:
          int rowCount(const QModelIndex & = QModelIndex()) const;
          int columnCount(const QModelIndex & = QModelIndex()) const;
          QVariant data(const QModelIndex &index, int role) const;
          QHash<int, QByteArray> roleNames() const;
      };
      
      #endif
      

      5/ tableViewModelExportGivav.cpp

      #include "tableViewModelExportGivav.h"
      
      int TableViewModelExportGivav::rowCount(const QModelIndex &iQModelIndex) const
      {
        return 20;
      }
      
      int TableViewModelExportGivav::columnCount(const QModelIndex &iQModelIndex) const
      {
        return 2;
      }
      
      QVariant TableViewModelExportGivav::data(const QModelIndex &iQModelIndex, int iRole) const
      {
        switch (iRole) {
            case Qt::DisplayRole:
                return QString("%1, %2").arg(iQModelIndex.column()).arg(iQModelIndex.row());
            default:
                break;
        }
      
        return QVariant();
      }
      
      QHash<int, QByteArray> TableViewModelExportGivav::roleNames() const
      {
        return { {Qt::DisplayRole, "display"} };
      }
      
      1 Reply Last reply
      0
      • 6thC6 Offline
        6thC6 Offline
        6thC
        wrote on last edited by 6thC
        #2

        I'm pretty sure what's happening here is your delegate is being reused there. Try changing the selections of all visible items... I think you'll find as you scroll it will get even funnier.

        In main.cpp you can add:

        int main(int argc, char *argv[])
        {
           qputenv("QSG_VISUALIZE", QByteArray("overdraw"));
        

        and you can see this more visually.

        My QML TableView has extra work on reuse such as:

        TableView.onReused: { delegate.doReUseWork(tableView.model); }
        

        In that function (so now delegate has an item / index etc, I'd ask the delegate to do the work to apply it's customisation / selections etc.

        https://doc.qt.io/qt-5/qml-qtquick-tableview.html
        You could also set https://doc.qt.io/qt-5/qml-qtquick-tableview.html#reuseItems-prop to false.

        1 Reply Last reply
        2
        • GrecKoG Online
          GrecKoG Online
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #3

          Or you could avoid storing state in the delegates.
          You should.

          1 Reply Last reply
          1
          • G Offline
            G Offline
            g0ku_0ne
            wrote on last edited by g0ku_0ne
            #4

            @6thC Thanks for your help. My bad, this is written in documentation and I missed it. So, I tried to use property "reuseItems : false;" or delegate (In order to use TableView.onReused) in TableView definition, but these keywords seems to be unknown (Error M16)
            So I modified my includes, and only kept :

            import QtQuick 2.12
            import QtQuick.Controls 2.5
            

            Now, "reuseItems and delegate" keywords are well reconized in TableView, but TableViewColumn becomes unknown (M300).

            I add to fix this issue :

            import QtQuick.Controls 1.4
            

            Now TableViewColumn are reconized, but "reuseItems" and "delegate" keywords no more ! -_-

            I don't know how to know what correct version of these component I have to use...


            @GrecKo Ok, I will keep that in mind. But in my example, could you please tell me which state I stored in delegate ?

            I didn't initialized combobox, and I don't stored anything on combo modification. I don't understand how "reuse" mecanism can work because it seems that previous selected index of another row is kept after reuse. If I don't reset manually the displayed value of the combobox for each reused row, what is displayed after scrolling is not what it was selected...

            6thC6 1 Reply Last reply
            0
            • G g0ku_0ne

              @6thC Thanks for your help. My bad, this is written in documentation and I missed it. So, I tried to use property "reuseItems : false;" or delegate (In order to use TableView.onReused) in TableView definition, but these keywords seems to be unknown (Error M16)
              So I modified my includes, and only kept :

              import QtQuick 2.12
              import QtQuick.Controls 2.5
              

              Now, "reuseItems and delegate" keywords are well reconized in TableView, but TableViewColumn becomes unknown (M300).

              I add to fix this issue :

              import QtQuick.Controls 1.4
              

              Now TableViewColumn are reconized, but "reuseItems" and "delegate" keywords no more ! -_-

              I don't know how to know what correct version of these component I have to use...


              @GrecKo Ok, I will keep that in mind. But in my example, could you please tell me which state I stored in delegate ?

              I didn't initialized combobox, and I don't stored anything on combo modification. I don't understand how "reuse" mecanism can work because it seems that previous selected index of another row is kept after reuse. If I don't reset manually the displayed value of the combobox for each reused row, what is displayed after scrolling is not what it was selected...

              6thC6 Offline
              6thC6 Offline
              6thC
              wrote on last edited by
              #5

              @g0ku_0ne

              But in my example, could you please tell me which state I stored in delegate ?

              The actual selection, when you interact with it. On reuse that selection "sticks". Technically, it never changes.
              It's sneaky but you probably wish to store the checked state / selected index|item Id / whatever in the model, somewhere else other than the delegate.

              import QtQuick.Controls 1.4
              Now TableViewColumn are reconized, but "reuseItems" and "delegate" keywords no more ! -_-

              I'd recommend you don't mix QtQuick.Controls 1 & 2
              My examples and links are assuming Controls v2 - the interfaces are different between both which is why you see this.

              To get a working Controls2 TableView with backend c++ data exposed I had to do a fair bit of reading:
              QML TableView (controls2) https://doc.qt.io/qt-5/qml-qtquick-tableview.html#example-usage
              https://doc.qt.io/qt-5/qabstractitemmodel.html
              https://doc.qt.io/qt-5/qabstracttablemodel.html
              https://doc.qt.io/qt-5/model-view-programming.html#model-classes

              It's a bit to take in if all these concepts are new to you but you can do it, you already have something right =)

              My use is only the first time I've used abstract models to expose a Qt model, up to now I've had basic lists supplied by just a QStringList etc and that's been fine.

              A need for a TableView at work had me learning this all too, I am sure I will still have many gaps. Always holes somewhere... I'm on a pretty brutal path balancing getting things done vs. time for R&D / on the job learning. No business wants to dedicate a resource to just learning but a good one to work for understands it often can be necessary.

              @GrecKo best/good advice is appreciated but a "don't do this" is always more fully appreciated when it's followed with context of what you should do.Everyone is learning something for the first time and some appreciation that this all particularly can be quite a lot to take in.

              I can make a guess as to what @GrecKo is implying. It'd help if this was confirmed/clarified as I'd like to not put words in anyone's mouth or worse, go down a completely wrong path on false assumptions.

              Also understand: this bit is new and uncharted territory for myself. I suspect my rework script to style the delegate on reuse is not the ideal. Most probably not.

              Reading more just now, I do remember seeing there are Selection Models https://doc.qt.io/qt-5/model-view-programming.html#using-a-selection-model

              At a glance it would appear this is exactly the purpose - to store selection information separately from the delegates and when time permits I will have to investigate further.

              My concerns without would primarily be: how much control of the selection styles and other visual behaviours I'd have using that. I do get R&D time on the job, not generally for things that are working without fault, even if performance or best practises are not optimal. Anyhow. Good luck and if there's any experts who uses models more fully - I know I'd appreciate the clarification.

              When I get to actually spending time reading this and trying it these issues may just resolve themselves / become non-concerns too.

              G 1 Reply Last reply
              1
              • 6thC6 6thC

                @g0ku_0ne

                But in my example, could you please tell me which state I stored in delegate ?

                The actual selection, when you interact with it. On reuse that selection "sticks". Technically, it never changes.
                It's sneaky but you probably wish to store the checked state / selected index|item Id / whatever in the model, somewhere else other than the delegate.

                import QtQuick.Controls 1.4
                Now TableViewColumn are reconized, but "reuseItems" and "delegate" keywords no more ! -_-

                I'd recommend you don't mix QtQuick.Controls 1 & 2
                My examples and links are assuming Controls v2 - the interfaces are different between both which is why you see this.

                To get a working Controls2 TableView with backend c++ data exposed I had to do a fair bit of reading:
                QML TableView (controls2) https://doc.qt.io/qt-5/qml-qtquick-tableview.html#example-usage
                https://doc.qt.io/qt-5/qabstractitemmodel.html
                https://doc.qt.io/qt-5/qabstracttablemodel.html
                https://doc.qt.io/qt-5/model-view-programming.html#model-classes

                It's a bit to take in if all these concepts are new to you but you can do it, you already have something right =)

                My use is only the first time I've used abstract models to expose a Qt model, up to now I've had basic lists supplied by just a QStringList etc and that's been fine.

                A need for a TableView at work had me learning this all too, I am sure I will still have many gaps. Always holes somewhere... I'm on a pretty brutal path balancing getting things done vs. time for R&D / on the job learning. No business wants to dedicate a resource to just learning but a good one to work for understands it often can be necessary.

                @GrecKo best/good advice is appreciated but a "don't do this" is always more fully appreciated when it's followed with context of what you should do.Everyone is learning something for the first time and some appreciation that this all particularly can be quite a lot to take in.

                I can make a guess as to what @GrecKo is implying. It'd help if this was confirmed/clarified as I'd like to not put words in anyone's mouth or worse, go down a completely wrong path on false assumptions.

                Also understand: this bit is new and uncharted territory for myself. I suspect my rework script to style the delegate on reuse is not the ideal. Most probably not.

                Reading more just now, I do remember seeing there are Selection Models https://doc.qt.io/qt-5/model-view-programming.html#using-a-selection-model

                At a glance it would appear this is exactly the purpose - to store selection information separately from the delegates and when time permits I will have to investigate further.

                My concerns without would primarily be: how much control of the selection styles and other visual behaviours I'd have using that. I do get R&D time on the job, not generally for things that are working without fault, even if performance or best practises are not optimal. Anyhow. Good luck and if there's any experts who uses models more fully - I know I'd appreciate the clarification.

                When I get to actually spending time reading this and trying it these issues may just resolve themselves / become non-concerns too.

                G Offline
                G Offline
                g0ku_0ne
                wrote on last edited by
                #6

                @6thC First, thank you so much for the time you spent to help me.

                This management of control is very different of all I have seen until now. I already coded a TableView in QT C++ side, without QML, and this was pretty simple...

                Regarding QtQuick.Controls 1 & 2, I no more mix the versions thanks to you, and I understand that TableViewColumn is no more available with version 2. I had a look to another response of GrecKo which help me to begin with a minimal working TableView here : https://forum.qt.io/topic/98076/qtquick-controls2-tableview/2

                I will have a look to the links you shared, and post my solution when all will worked, if it can help other people...

                Once again, thank you :o)

                6thC6 1 Reply Last reply
                2
                • G g0ku_0ne

                  @6thC First, thank you so much for the time you spent to help me.

                  This management of control is very different of all I have seen until now. I already coded a TableView in QT C++ side, without QML, and this was pretty simple...

                  Regarding QtQuick.Controls 1 & 2, I no more mix the versions thanks to you, and I understand that TableViewColumn is no more available with version 2. I had a look to another response of GrecKo which help me to begin with a minimal working TableView here : https://forum.qt.io/topic/98076/qtquick-controls2-tableview/2

                  I will have a look to the links you shared, and post my solution when all will worked, if it can help other people...

                  Once again, thank you :o)

                  6thC6 Offline
                  6thC6 Offline
                  6thC
                  wrote on last edited by
                  #7

                  @g0ku_0ne
                  Anytime.

                  And: https://doc.qt.io/qt-5/qml-qt-labs-qmlmodels-tablemodel.html cool - that other post I wasn't aware of TableModel, I use ListModels for quick datamodels of static data /unlikely to change a fair bit - it's nice to know that if I ever need a quick table populated - I can declare it in QML the same.

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    g0ku_0ne
                    wrote on last edited by
                    #8

                    Hi all,

                    I resume here all problems I faced :

                    First I developped my application with QT 5.12.6. The original issue is the display value of combobox (contained in a TableView) which randomly changed on hidden combo after scrolling back. Video : streamable.com/in6nh

                    Thanks to @6thC, I understand that the delegate of hidden combobox is reused for shown combobox, this is a new behavior described here : https://www.qt.io/blog/2018/08/29/tableview.

                    But in my original case, I used TableView with TableViewColumn, which is the old version. (import QtQuick 2.12 import QtQuick.Controls 1.4)
                    So why am I impacted by this new behavior ? This is a good question, and I don't know the answer. If someone has a clue ...

                    Anyway, I'm stuck with a TableView 1.0, which has the "reuse" behavior BUT which do not provide TableView.onPooled and TableView.onReused signals... So from my point of view, this is a bug and I have to use the new TableView.

                    So I change my code to use the full TableView 2.0, still in 5.12.6 : I replace "import QtQuick.Controls 1.4" by "import QtQuick.Controls 2.5". TableViewColumn is no more accessible, so columns can no more be defined in qml because : 
                    "A TableView displays data from models created from built-in QML types such as ListModel and XmlListModel, which populates the first column only in a TableView. To create models with multiple columns, create a model in C++ that inherits QAbstractItemModel, and expose it to QML."Extract from : https://doc.qt.io/qt-5.12/qml-qtquick-tableview.html  
                    Arg !!! In QT 5.14, there is a TableModel which allow you the colums definition in qml file : https://doc-snapshots.qt.io/qt5-5.14/qml-qt-labs-qmlmodels-tablemodel.html
                    But I prefere to not migrate my project on QT 5.14, because it's quite a big project, and each migration comes with new errors to fix... So, ok, let's implement a model in C++, I the model here : took https://doc.qt.io/qt-5.12/qml-qtquick-tableview.html. Now I can define the number of column I want. Great !
                    On Qml side, I implement a combobox delegate, with a simple static model, with reuseItems enable : Still not working. As soon as a delegate is pool/reuse while scrolling, the display value does'nt match with the expected one, even I don't change anything, It's full random.

                    So I tried to implement "TableView.onReused" : Each time "onReused" is called, I look into an array (filled with callback "onActivated" of the combo, to store the selected index.) the correct index. The table seems to be well filled, but display is still random. That's boring.

                    So I tried to disable "reuse" mechanism, and initialize on the onCompleted of combo delegate  the correct index, stored in the array.

                    FANTASTIC, it finally works !!!! OMG so many steps to just display combo in a table ...

                    Just below is the code I use, not just a sentence, not just some parts : ALL THE CODE. Maybe it's not the best code to do what I want to do, but it works ! If you want other component than combobox in your delegate of TableView, I tested to create a CheckBox, and It seems to well work. But I don't implement the array to store the values. It's the same mechanism than the combobox.

                    If someone find a way to do the same think with "reuse" mechanism enable, I take.

                    Thanks for your patience,

                    G0ku

                    There are 5 files :
                    1/ main.qml
                    2/ CheckBox.qml
                    3/ ComboBox.qml
                    4/ tableViewModelExportGivav.h
                    5/ tableViewModelExportGivav.cpp

                    1/ main.qml

                    import QtQuick 2.12
                    import QtQuick.Controls 2.5
                    // Dummy model, required to create more than one column
                    import TableViewModelExportGivav 0.1
                    
                    ApplicationWindow {
                        id: idAppWindow
                    
                        visible: true
                        width: 640
                        height: 480
                    
                        title: qsTr("Scroll test")
                    
                        // Component created in the delegate of the TableView
                        property variant myComponent;
                    
                        // Array which store the selected index of all the combobox of the TableView
                        property variant tabIndexComboBox : [];
                    
                        // Retrieve the data position on the list tabIndexComboBox
                        function findPosInArray(iRow, iColumn)
                        {
                            var posToReturn = -1;
                    
                            for(var i=0; i<tabIndexComboBox.length;i++)
                            {
                                var indexObjectExisting = tabIndexComboBox[i];
                    
                                if( (indexObjectExisting._row===iRow) && (indexObjectExisting._column===iColumn) )
                                {
                                    posToReturn = i;
                                    break;
                                }
                            }
                    
                            console.log("findPosInArray : called with iRow=" + iRow + " and iColumn=" + iColumn + ", returned index=" + posToReturn);
                    
                            return posToReturn;
                        }
                    
                        // Add data position on the list tabIndexComboBox
                        function manageIndex(iRow, iColumn, iIndex) {
                            var indexObject = {};
                            indexObject._row = iRow;
                            indexObject._column = iColumn;
                            indexObject._selectedIndex = iIndex;
                    
                            var indexCb = findPosInArray(iRow, iColumn);
                            if(-1 === indexCb)
                            {
                                tabIndexComboBox.push(indexObject);
                                console.log("manageIndex : object non trouve et ajoute index=" + iIndex);
                            }
                            else
                            {
                                tabIndexComboBox[indexCb] = indexObject;
                                console.log("manageIndex : object trouve et MAJ index=" + iIndex);
                            }
                    
                            console.log("manageIndex.length : " + tabIndexComboBox.length);
                        }
                    
                        // Retrieve selected index of the combobox
                        function retrieveIndex(iRow, iColumn) {
                            var indexToRetrieve = -1;
                            var indexCb = findPosInArray(iRow, iColumn);
                    
                            if(-1 !== indexCb)
                                indexToRetrieve = tabIndexComboBox[indexCb]._selectedIndex;
                    
                            return indexToRetrieve;
                        }
                    
                        Component  {
                            id: idTableViewDelegate
                    
                            Rectangle {
                                id:idRect
                                implicitWidth: 150
                                implicitHeight: 50
                    
                                Component.onCompleted: {
                                    if(column === 0)
                                    {
                                        myComponent = Qt.createComponent("qrc:///CheckBox.qml");
                                    }
                                    else if(column === 1)
                                    {
                                        myComponent = Qt.createComponent("qrc:///ComboBox.qml");
                                    }
                    
                                    if (myComponent.status === Component.Ready)
                                    {
                                       //console.log("myComponent is ready");
                                       myComponent.createObject(idRect, {x: idRect.x, y: idRect.y});
                                    }
                                    else
                                    {
                                        //console.log("myComponent is NOT ready");
                                        myComponent.statusChanged.connect(finishCreationComponent);
                                    }
                                }
                    
                                TableView.onReused: {
                                    console.log("TableView.onReused : AIE AIE AIE");
                                }
                            }
                        }
                    
                        function finishCreationComponent(iStatus) {
                            // Not required
                        }
                    
                        Row{
                            id:idRow
                            Button {
                                id:idButtonDump
                                text:"Dump"
                                onPressed: {
                                    console.log("DUMP START tabIndexComboBox");
                                    for(var i=0; i<tabIndexComboBox.length;i++)
                                    {
                                        var indexObjectExisting = tabIndexComboBox[i];
                    
                                        console.log("tabIndexComboBox i=" + i + ", value=" + JSON.stringify(indexObjectExisting));
                                    }
                                    console.log("DUMP STOP tabIndexComboBox");
                                }
                            }
                    
                    
                            Button {
                                id:idButtonClear
                                text:"Clear"
                                onPressed: {
                                    tabIndexComboBox = [];
                                }
                            }
                        }
                    
                        TableView {
                            id:idTableView
                    
                            anchors.top:idRow.bottom
                            anchors.bottom:parent.bottom
                            anchors.right:parent.right
                            anchors.left:parent.left
                    
                            model : TableViewModelExportGivav {
                    
                            }
                    
                            delegate: idTableViewDelegate;
                    
                            reuseItems:false
                        }
                    }
                    

                    2/ CheckBox.qml

                    import QtQuick 2.12
                    import QtQuick.Controls 2.5
                    
                    Rectangle {
                        CheckBox {
                            id: idCheckBoxDelegate
                    
                            Component.onCompleted: {
                                console.log("idCheckBoxDelegate.onCompleted");
                            }
                    
                        }
                    }
                    

                    3/ ComboBox.qml

                    import QtQuick 2.12
                    import QtQuick.Controls 2.5
                    
                    Rectangle {
                    
                        ComboBox {
                            id: idComboBoxDelegate
                    
                            model: [ {"text":"Banana"}, {"text":"Apple"}, {"text":"Coconut"} ]
                            textRole: "text";
                    
                            Component.onCompleted: {
                                console.log("idComboBoxDelegate.onCompleted for row=" + row);
                    
                                currentIndex = idAppWindow.retrieveIndex(row, column);
                            }
                    
                            //currentIndex: idAppWindow.retrieveIndex(row, column);
                    
                            onActivated: {
                                console.log("checkBoxDelegate.onCurrentIndexChanged : row=" + row + ", column=" + column + ", value set to : " + index);
                    
                                idAppWindow.manageIndex(row, column, index);
                            }
                        }
                    }
                    

                    4/ tableViewModelExportGivav.h

                    #ifndef TableViewModelExportGivav_H
                    #define TableViewModelExportGivav_H
                    
                    #include <QObject>
                    #include <QAbstractTableModel>
                    
                    class TableViewModelExportGivav : public QAbstractTableModel
                    {
                        Q_OBJECT
                    
                    public:
                        int rowCount(const QModelIndex & = QModelIndex()) const;
                        int columnCount(const QModelIndex & = QModelIndex()) const;
                        QVariant data(const QModelIndex &index, int role) const;
                        QHash<int, QByteArray> roleNames() const;
                    };
                    
                    #endif
                    

                    5/ tableViewModelExportGivav.cpp

                    #include "tableViewModelExportGivav.h"
                    
                    int TableViewModelExportGivav::rowCount(const QModelIndex &iQModelIndex) const
                    {
                      return 20;
                    }
                    
                    int TableViewModelExportGivav::columnCount(const QModelIndex &iQModelIndex) const
                    {
                      return 2;
                    }
                    
                    QVariant TableViewModelExportGivav::data(const QModelIndex &iQModelIndex, int iRole) const
                    {
                      switch (iRole) {
                          case Qt::DisplayRole:
                              return QString("%1, %2").arg(iQModelIndex.column()).arg(iQModelIndex.row());
                          default:
                              break;
                      }
                    
                      return QVariant();
                    }
                    
                    QHash<int, QByteArray> TableViewModelExportGivav::roleNames() const
                    {
                      return { {Qt::DisplayRole, "display"} };
                    }
                    
                    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