Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED]How to update the TableView in QML or C++?
Forum Updated to NodeBB v4.3 + New Features

[SOLVED]How to update the TableView in QML or C++?

Scheduled Pinned Locked Moved General and Desktop
11 Posts 2 Posters 8.6k Views 2 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.
  • C Offline
    C Offline
    CoderJeff
    wrote on last edited by CoderJeff
    #1

    I am coding a program combining QML and C++. The TableView shows a column of a table. I can add or delete the record correctly, but I can not update the TableView, which always shows the content before adding or deleting.

    How to update the TableView?

    PS: I do not know whether it is good choice to code with QML and C++ instead of QWidget directly. At least by now, it keeps frustrating me.

    p3c0P 1 Reply Last reply
    0
    • C CoderJeff

      I am coding a program combining QML and C++. The TableView shows a column of a table. I can add or delete the record correctly, but I can not update the TableView, which always shows the content before adding or deleting.

      How to update the TableView?

      PS: I do not know whether it is good choice to code with QML and C++ instead of QWidget directly. At least by now, it keeps frustrating me.

      p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by p3c0
      #2

      Hi @CoderJeff,
      Assuming you are using QAbstractTableModel or QAbstractItemModel as C++ model with QML, to update the view, use setData to update the model and then fire the dataChanged signal with appropriate index to notify the view about the changes.
      It would be helpful if you post some code.

      I do not know whether it is good choice to code with QML and C++ instead of QWidget directly. At least by now, it keeps frustrating me.

      It totally depends upon your requirements.

      157

      C 1 Reply Last reply
      0
      • p3c0P p3c0

        Hi @CoderJeff,
        Assuming you are using QAbstractTableModel or QAbstractItemModel as C++ model with QML, to update the view, use setData to update the model and then fire the dataChanged signal with appropriate index to notify the view about the changes.
        It would be helpful if you post some code.

        I do not know whether it is good choice to code with QML and C++ instead of QWidget directly. At least by now, it keeps frustrating me.

        It totally depends upon your requirements.

        C Offline
        C Offline
        CoderJeff
        wrote on last edited by
        #3

        @p3c0

        Actually, I am using QSqlTableModel.

        class MySqlModel : public QSqlTableModel
        {
        ......
        void addRecord(field1,field2, ..., fieldN);
        void deleteRecord();
        void updateRecord(field1, field2, ..., fieldN);
        ......
        }

        The TableView in QML has only one column.

        After running addRecord() and deleteRecord(), I want to update the content of TableView. But I do not know how to do it. The following is a part of my code.

        main() {
        //other code
        ......

        MySqlModel *model = new MySqlModel;
        model->QSqlQueryModel::setQuery("SELECT FieldName1 FROM Table");

        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty ("SQQL", model);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

        //other code
        ......
        }

        In the qml:
        TableView{
        //other code
        ......

        model: SQQL

        //other code
        ......
        }

        How to use setData and dataChanged to connect MySqlModel in C++ and TableView in QML?

        p3c0P 1 Reply Last reply
        0
        • C CoderJeff

          @p3c0

          Actually, I am using QSqlTableModel.

          class MySqlModel : public QSqlTableModel
          {
          ......
          void addRecord(field1,field2, ..., fieldN);
          void deleteRecord();
          void updateRecord(field1, field2, ..., fieldN);
          ......
          }

          The TableView in QML has only one column.

          After running addRecord() and deleteRecord(), I want to update the content of TableView. But I do not know how to do it. The following is a part of my code.

          main() {
          //other code
          ......

          MySqlModel *model = new MySqlModel;
          model->QSqlQueryModel::setQuery("SELECT FieldName1 FROM Table");

          QQmlApplicationEngine engine;
          engine.rootContext()->setContextProperty ("SQQL", model);
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

          //other code
          ......
          }

          In the qml:
          TableView{
          //other code
          ......

          model: SQQL

          //other code
          ......
          }

          How to use setData and dataChanged to connect MySqlModel in C++ and TableView in QML?

          p3c0P Offline
          p3c0P Offline
          p3c0
          Moderators
          wrote on last edited by
          #4

          @CoderJeff Are addRecord, updateRecord accessible from QML ?
          Once you have called say addRecord(int field1) you need to call setData() after it to update the model and dataChanged() with proper index.
          An example from one of my code:

          void PicModel::updateTitle(int row, int col, QString title)
          {
              QModelIndex modelIndex = this->index(row,col);
              setData(modelIndex, title, TitleRole);
              return;
          }
          
          bool PicModel::setData(const QModelIndex &index, const QVariant &value, int role)
          {
              if (role == TitleRole) {
                  m_data[index.row()].m_title = value.toString(); //Just a list which holds 'struct' of pics info
              }
              emit dataChanged(index, index);
              return true;
          }
          

          So from QML updateTitle is invoked with parameters (row and title) and the rest code updates the QList (data holder) and then updates the view.

          157

          C 1 Reply Last reply
          0
          • p3c0P p3c0

            @CoderJeff Are addRecord, updateRecord accessible from QML ?
            Once you have called say addRecord(int field1) you need to call setData() after it to update the model and dataChanged() with proper index.
            An example from one of my code:

            void PicModel::updateTitle(int row, int col, QString title)
            {
                QModelIndex modelIndex = this->index(row,col);
                setData(modelIndex, title, TitleRole);
                return;
            }
            
            bool PicModel::setData(const QModelIndex &index, const QVariant &value, int role)
            {
                if (role == TitleRole) {
                    m_data[index.row()].m_title = value.toString(); //Just a list which holds 'struct' of pics info
                }
                emit dataChanged(index, index);
                return true;
            }
            

            So from QML updateTitle is invoked with parameters (row and title) and the rest code updates the QList (data holder) and then updates the view.

            C Offline
            C Offline
            CoderJeff
            wrote on last edited by
            #5

            @p3c0 said:

            Are addRecord, updateRecord accessible from QML ?

            Yes.

            I tried, but it does not work.

            void MySqlModel::addRecord(const QString &str1)
            {
            //add a record
            ......

            //update the model
            QSqlQueryModel::setQuery("SELECT FieldName1 FROM Table");
            int ct = this->rowCount();
            QModelIndex modelIndex = this->index(ct-1,0);
            this->setData(modelIndex, str1, PortName);
            ......
            }

            I did not overload the setData since I have no class member m_data like yours. I only update the instance of MySqlModel.

            p3c0P 1 Reply Last reply
            0
            • C CoderJeff

              @p3c0 said:

              Are addRecord, updateRecord accessible from QML ?

              Yes.

              I tried, but it does not work.

              void MySqlModel::addRecord(const QString &str1)
              {
              //add a record
              ......

              //update the model
              QSqlQueryModel::setQuery("SELECT FieldName1 FROM Table");
              int ct = this->rowCount();
              QModelIndex modelIndex = this->index(ct-1,0);
              this->setData(modelIndex, str1, PortName);
              ......
              }

              I did not overload the setData since I have no class member m_data like yours. I only update the instance of MySqlModel.

              p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by
              #6

              @CoderJeff Well then in case of add, use beginInsertRows and endInsertRows. This too will update the model and thus the view. Can you post the complete code ? Its harder to guess how you are trying to implement it.

              157

              C 1 Reply Last reply
              0
              • p3c0P p3c0

                @CoderJeff Well then in case of add, use beginInsertRows and endInsertRows. This too will update the model and thus the view. Can you post the complete code ? Its harder to guess how you are trying to implement it.

                C Offline
                C Offline
                CoderJeff
                wrote on last edited by
                #7

                @p3c0

                C++ code:

                class MySqlModel : public QSqlTableModel
                {
                Q_OBJECT

                public:
                MySqlModel(QObject *parent = 0);
                ~MySqlModel();

                enum Roles {
                    Field1 = Qt::UserRole + 1,
                    Field2
                };
                
                QHash<int, QByteArray> roleNames() const;
                QVariant data(const QModelIndex &index, int role) const;
                
                Q_INVOKABLE void addRecord(const QString &str1, const QString &str2, const QString &str3);
                

                private:
                static void createConnection();
                static void closeConnection();

                static QSqlDatabase m_db;
                

                };

                QHash<int, QByteArray> MySqlModel::roleNames() const
                {
                QHash<int, QByteArray> roles;
                roles[Field1] = "field1";
                roles[Field2] = "field2";
                return roles;
                }

                QVariant MySqlModel::data(const QModelIndex &index, int role) const
                {
                if (!index.isValid())
                return QVariant();

                QString fieldName;
                switch (role) {
                    case Field1: fieldName = QStringLiteral("FieldName1"); break;
                    case Field2: fieldName = QStringLiteral("FieldName2"); break;
                 }
                if (!this->record().isGenerated(fieldName))
                    return QVariant();
                else {
                    QModelIndex item = indexInQuery(index);
                    if ( !this->query().seek(item.row()) )
                        return QVariant();
                    return this->query().value(fieldName);
                }
                return QVariant();
                

                }

                void MySqlModel::addRecord(const QString &str1, const QString &str2, const QString &str3)
                {
                QSqlQuery query;
                bool bPrepare = query.prepare("INSERT INTO Portfolio (fieldName1, "
                "fieldName2,"
                "fieldName3)"
                "VALUES (?,?,?)");

                query.addBindValue(str1);
                query.addBindValue(str2);
                query.addBindValue(str3);
                query.exec();
                

                QSqlQueryModel::setQuery("SELECT FieldName1 FROM Portfolio")
                int ct = this->rowCount();

                QModelIndex modelIndex = this->index(ct-1,0);
                this->setData(modelIndex, str1, Field1);
                
                return;
                

                }

                Qml code:
                TableView{
                id: myTableView
                objectName: "myTableViewObj"
                anchors.top: rowRadio.bottom
                anchors.left: rowRadio.left
                anchors.right: rowRadio.right
                anchors.bottom: parent.bottom
                anchors.topMargin: 8
                TableViewColumn{ role: "field1"; title: "FieldName1"}
                headerVisible: false
                model: SQQL
                }

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  CoderJeff
                  wrote on last edited by
                  #8

                  I changed my code. It works finally.

                  Add a Q_INVOKABLE function:

                  Q_INVOKABLE QObject* model()
                  {
                  QSqlQueryModel::setQuery("SELECT FieldName1 FROM Portfolio")
                  return mySqlModelInstance;
                  }

                  In QML, after calling addRecord or deleteRecord, call the above function and update the TableView's model.

                  {
                  ......
                  myModel.addRecord();
                  tableView.model = myModel.model();
                  ......
                  }

                  {
                  ......
                  myModel.deleteRecord();
                  tableView.model = myModel.model();
                  ......
                  }

                  I did not use setData or dataChanged.

                  p3c0P 1 Reply Last reply
                  0
                  • C CoderJeff

                    I changed my code. It works finally.

                    Add a Q_INVOKABLE function:

                    Q_INVOKABLE QObject* model()
                    {
                    QSqlQueryModel::setQuery("SELECT FieldName1 FROM Portfolio")
                    return mySqlModelInstance;
                    }

                    In QML, after calling addRecord or deleteRecord, call the above function and update the TableView's model.

                    {
                    ......
                    myModel.addRecord();
                    tableView.model = myModel.model();
                    ......
                    }

                    {
                    ......
                    myModel.deleteRecord();
                    tableView.model = myModel.model();
                    ......
                    }

                    I did not use setData or dataChanged.

                    p3c0P Offline
                    p3c0P Offline
                    p3c0
                    Moderators
                    wrote on last edited by
                    #9

                    @CoderJeff But then you are assigning model and again and again when something is added or removed. Instead try to use beginResetModel and beginInsertRows.

                    157

                    C 1 Reply Last reply
                    0
                    • p3c0P p3c0

                      @CoderJeff But then you are assigning model and again and again when something is added or removed. Instead try to use beginResetModel and beginInsertRows.

                      C Offline
                      C Offline
                      CoderJeff
                      wrote on last edited by
                      #10

                      @p3c0

                      I will try it.

                      QML almost drives me crazy.

                      I am making a desktop program. I find it is very inconvenient to integrate QML and C++ while it is much more convenient using QWidget. I check the difference between QML and QWidget. QML is encapsulated and all its elements are private. It is not easy to access the elements of QML. On the contrary, QWidget on GUI are public. User can access them freely.

                      Do you agree with me?

                      p3c0P 1 Reply Last reply
                      0
                      • C CoderJeff

                        @p3c0

                        I will try it.

                        QML almost drives me crazy.

                        I am making a desktop program. I find it is very inconvenient to integrate QML and C++ while it is much more convenient using QWidget. I check the difference between QML and QWidget. QML is encapsulated and all its elements are private. It is not easy to access the elements of QML. On the contrary, QWidget on GUI are public. User can access them freely.

                        Do you agree with me?

                        p3c0P Offline
                        p3c0P Offline
                        p3c0
                        Moderators
                        wrote on last edited by
                        #11

                        @CoderJeff Well new QtQuick Controls are still evolving. Many of the important properties are still under development and hence they are private.

                        I find it is very inconvenient to integrate QML and C++ while it is much more convenient using QWidget

                        Depends upon the requirement. I have been using components like Item, ListView etc.. with C++ with no problem. Finding Items, connecting to QML signals too work.

                        QML is encapsulated and all its elements are private.

                        Yes they are (assuming creating from C++). But you can create Items from C++ using QQuickItem. May there are troubles in making them public. Or may be in future they could be made public. Or may be they are not meant to be made.

                        157

                        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