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. Gridview dynamic update on C++ model setData() or qml ListModel set()
Forum Updated to NodeBB v4.3 + New Features

Gridview dynamic update on C++ model setData() or qml ListModel set()

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
the
6 Posts 5 Posters 1.8k 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.
  • faburF Offline
    faburF Offline
    fabur
    wrote on last edited by
    #1

    Hi all,

    I'm having problems understanding why this is not working, I just want to have an item in the view dynamically updated when I change the data in the model using the ListModel method set() , I've also used a C++ model and setData() which emits dataChanged() signal but I can't see any refresh though. I'm stucked.

    import QtQuick 2.5
    import QtQuick.Controls 2.2
    import QtQuick.Layouts 1.2
    
    
    Dialog {
        id: mydialog
        anchors.centerIn: parent
        width: parent.width / 2
        height: parent.height / 2
        padding: 32
        modal: true
    
        ListModel {
            id: theModel
    
            ListElement { number: 0 }
            ListElement { number: 1 }
            ListElement { number: 2 }
            ListElement { number: 3 }
            ListElement { number: 4 }
            ListElement { number: 5 }
            ListElement { number: 6 }
            ListElement { number: 7 }
            ListElement { number: 8 }
            ListElement { number: 9 }
        }
    
        ColumnLayout {
            anchors.fill: parent
    
            property int count: 9
    
            Button {
                Layout.alignment: Qt.AlignTop
                Layout.preferredHeight: 20
                Layout.preferredWidth : 50
    
                text: qsTr("add")
    
                onClicked: {
                    console.debug("add element")
                    theModel.append({"number": ++parent.count});
                }
    
            }
    
            Button {
                Layout.alignment: Qt.AlignCenter
                Layout.preferredHeight: 20
                Layout.preferredWidth : 50
    
                text: qsTr("set")
    
                onClicked: {
                    console.debug("set")
                    theModel.set(0, {"number": 12});
                }
    
            }
    
            GridView {
                Layout.alignment: Qt.AlignBottom
                id: view
                Layout.preferredHeight: 100
                Layout.preferredWidth : 400
                //anchors.margins: 20
    
                clip: true
    
                model: theModel
    
                cellWidth: 45
                cellHeight: 45
    
                delegate: numberDelegate
            }
    
            Component {
                id: numberDelegate
    
                Label {
                    width: 400
                    height: 40
                    text: index
                }
            }
    
        }
    }
    
    

    follows a second attempt which is more my real case ( I have a custom C++ model ) registered in My.Models 1.0 -> MyModel . It's bit better as I'm able to change the values in the view but the view items are not refreshed until I scroll up or down. Using grid.forceLayout() didn't solve, the only solution I've found is to set grid.model = 0 and reset the model with grid.model = mymodel . I expect this to work without any special trick. here is the code ( I've stripped it lot of lines so maybe the syntax is not correct, hope it's enough ):

    import QtQuick 2.12
    import QtQuick.Controls 2.5
    import QtQuick.Layouts 1.3
    import QtQuick.Controls.Material 2.3
    
    import My.Models 1.0
    
    Dialog {
        id: root
    
        anchors.centerIn: parent
        width: 1000
        height: 700
        padding: 32
        modal: true
    
        Connections {
            target: MyClass
            // MyClass emit this signal
            onFinishedParsing: {
                // this is an example trying to set all model data to "0.2" , in a real case this data come from MyClass
                for (var i = 0; i < mymodel.rowCount(); i++) {
                    mymodel.setData(mymodel.index(i, 0),"0.2",MyModelModel.Value)
                    }
        }
        
        ColumnLayout {
            anchors.fill: parent
            spacing: 16
    
           GridView {
                id: grid
                Layout.fillHeight: true
                Layout.fillWidth: true
                contentWidth: width
                cellWidth: width / 4
                cellHeight: 80
                clip: true
    
                model: MyModel {
                    id: mymodel
                    }
    
                delegate: Label {
                    text: model.value
                }
            }
    }
    

    the setData method in MyModel is:

    bool SimplsModel::setData(const QModelIndex &index, const QVariant &value,
                              int role) {
      if (index.isValid() && role == SimplsModel::Roles::Value) {
        m_rowData[index.row()].value = value.toFloat();
        emit dataChanged(index, index, {SimplsModel::Roles::Value});
        return true;
      }
      return false;
    }
    

    I'm really stucked , can't see what's wrong. any help would be really appreciated. thanks.

    1 Reply Last reply
    0
    • Q Offline
      Q Offline
      qyvlik
      wrote on last edited by
      #2

      Here is my code which use the QAbstractListModel: TestModel

      When change the data, try call beginResetModel and endResetModel .

      void TestModel::addDao(const QString &name, int age)
      {
          beginResetModel();
          m_datas.append(Dao(name, age));
          endResetModel();
      }
      
      faburF 1 Reply Last reply
      0
      • 6thC6 Offline
        6thC6 Offline
        6thC
        wrote on last edited by
        #3

        When change the data, try call beginResetModel and endResetModel.

        Don't (I wouldn't anyhow) do that, that's a big hammer. I do use that but only for a whole set of data.
        For an simple append ~not really right.

        setData & emit dataChanged is correct.

        When reimplementing the setData() function, this signal must be emitted explicitly.

        I emit that the whole row changed with mine (see the first 2 args below), but I'm not sure even this is fully optimal. It does work for me - just working is enough for me atm and I'd like to get time to experiment restricting to a unique.

          emit QAbstractTableModel::dataChanged(QAbstractTableModel::index(intOfIter, 0), QAbstractTableModel::index(intOfIter, columnCount()-1), QVector<int>() << role);
        

        I'm still getting my head around trying to get setData actually working from QML side with custom roles, from Table view but this works from Cpp backend, I'm trying to get a complex control sorted that can handle updates with dynamic delegates from QML.

        Hopefully this is just enough to get you across the line and moving again too.

        1 Reply Last reply
        0
        • Q qyvlik

          Here is my code which use the QAbstractListModel: TestModel

          When change the data, try call beginResetModel and endResetModel .

          void TestModel::addDao(const QString &name, int age)
          {
              beginResetModel();
              m_datas.append(Dao(name, age));
              endResetModel();
          }
          
          faburF Offline
          faburF Offline
          fabur
          wrote on last edited by
          #4

          @qyvlik

          beginResetModel() / endResetModel()
          

          works but actually is a lot of overhead in in setData, I think it's ok if I want to upadate the whole model data in one shot , thanks

          @6thC

          I've tried this but it didn't solve, as before it do set the data but the view doesn't refresh de delagates, maybe I didn't realize how to apply it for a QAbstractListModel:

          emit QAbstractListModel::dataChanged(QAbstractListModel::index(index.row()), QAbstractListModel::index(index.row()), QVector<int>() << SimplsModel::Roles::Value); 
          
          or 
          
          emit QAbstractListModel::dataChanged(QAbstractListModel::index(index.row()), QAbstractListModel::index(index.row()), QVector<int>() << Qt::DisplayRole);
          

          Strange that we have to fight to make this work, I can't find code examples about people achieving this, Am I doing something unusual ? ( I wander )

          thanks

          1 Reply Last reply
          0
          • C Offline
            C Offline
            Compozitor
            wrote on last edited by
            #5

            Try calling a signal without the last parameter.

            emit dataChanged(index, index);
            
            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bob64
              wrote on last edited by
              #6

              If I understood correctly, it wasn't even working for a QML ListModel. I think that would need to be resolved first before getting bogged down with the C++ model.

              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