Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

The model inherited from QAbstractTableModel throws errors



  • Hi!
    The model inherited from QAbstractTableModel throws errors : invalid new-expression of abstract class type 'MyModel'
    How do I fix this error?

    class MyModel : public QAbstractTableModel
    {
        Q_OBJECT
    public:
        enum Roles {
            Role1 = Qt::UserRole + 1,
            Role2,
            Role3
        };
    
        MyModel(QObject *parent = 0);
    
        void addRow(QString str1, QString str2, QString str3);
    
        int rowCount(const QModelIndex & parent = QModelIndex()) const;
    
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    
    protected:
        QHash<int, QByteArray> roleNames() const;
    private:
        QList <QString> list1, list2, list3;
    };
    
    #include "mymodel.h"
    
    MyModel::MyModel(QObject *parent)
        : QAbstractTableModel(parent)
    {
    }
    
    void MyModel::addRow(QString str1, QString str2, QString str3)
    {
        list1.append(str1);
        list2.append(str2);
        list3.append(str3);
    }
    
    int MyModel::rowCount(const QModelIndex & parent) const {
        Q_UNUSED(parent);
        return list1.count();
    }
    
    QVariant MyModel::data(const QModelIndex & index, int role) const {
        if (index.row() < 0 || index.row() >= list1.count())
            return QVariant();
    
        if(index.column() == 0){
            return list1[index.row()];
        }
        if(index.column() == 1){
            return list2[index.row()];
        }
        if(index.column() == 2){
            return list3[index.row()];
        }
        return QVariant();
    }
    
    QHash<int, QByteArray> MyModel::roleNames() const {
        QHash<int, QByteArray> roles;
        roles[Role1] = "role1";
        roles[Role2] = "role2";
        roles[Role3] = "role3";
        return roles;
    }
    

  • Lifetime Qt Champion

    Hi,

    Looks like you did not re-implement all the required methods.

    Note that you are not implementing your addRow method correctly. You are missing the begin/endInsertRows call.



  • I append this and now its normal and now it compiles normally

    int MyModel::columnCount(const QModelIndex &parent) const
    {
        return 3;
    }
    

    How to set the addRow() method correctly, now it looks like this:
    void MyModel::addRow(QString str1, QString str2, QString str3)
    {
    beginInsertRows( QModelIndex(), 0, 2 );
    list1.append(str1);
    list2.append(str2);
    list3.append(str3);
    endInsertRows();
    }



  • And this model is not displayed in the table in QML:

    class MyModel : public QAbstractTableModel
    {
        Q_OBJECT
    
    public:
        enum Roles {
            Role1 = Qt::UserRole + 1,
            Role2,
            Role3
        };
    
        MyModel(QObject *parent = nullptr);
    
        void addRow(QString str1, QString str2, QString str3);
    
        int columnCount(const QModelIndex &parent) const;
    
        int rowCount(const QModelIndex & parent = QModelIndex()) const;
    
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    
    protected:
        QHash<int, QByteArray> roleNames() const;
    private:
        QList <QString> list1, list2, list3;
    };
    
    #include "mymodel.h"
    
    MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent)
    {
        list1<<"11"<<"111"<<"1111";
        list2<<"22"<<"222"<<"2222";
        list3<<"33"<<"333"<<"3333";
    }
    
    void MyModel::addRow(QString str1, QString str2, QString str3)
    {
        beginInsertRows( QModelIndex(), 0, 2 );
        list1.append(str1);
        list2.append(str2);
        list3.append(str3);
        endInsertRows();
    }
    
    int MyModel::columnCount(const QModelIndex &parent) const
    {
        return 3;
    }
    
    int MyModel::rowCount(const QModelIndex & parent) const {
        Q_UNUSED(parent);
        return list1.count();
    }
    
    QVariant MyModel::data(const QModelIndex & index, int role) const {
        if (index.row() < 0 || index.row() >= list1.count())
            return QVariant();
    
        if(index.column() == 0){
            return list1[index.row()];
        }
        if(index.column() == 1){
            return list2[index.row()];
        }
        if(index.column() == 2){
            return list3[index.row()];
        }
        return QVariant();
    }
    
    QHash<int, QByteArray> MyModel::roleNames() const {
        QHash<int, QByteArray> roles;
        roles[Role1] = "role1";
        roles[Role2] = "role2";
        roles[Role3] = "role3";
        return roles;
    }
    


  • Still, my code works. Only 2 and 3 columns are the same as 1. How do I fix this?


  • Lifetime Qt Champion

    Why did you make roleNames protected ?
    It's a public method.


  • Qt Champions 2019

    And you should only return values for Qt::DisplayRole. And you should not delete your posts.



  • Sorry, I accidentally deleted it and couldn't restore it. The column index is always 0. What is the bug and how to fix it?

    #ifndef MYMODEL_H
    #define MYMODEL_H
    
    #include <QObject>
    #include <QAbstractTableModel>
    #include "QSize"
    #include "QBrush"
    #include "QFont"
    #include "QTime"
    #include <QAbstractListModel>
    #include <QStringList>
    #include "QDebug"
    
    //class MyModel : public QSqlTableModel
    //class MyModel : public QAbstractListModel
    class MyModel : public QAbstractTableModel
    {
        Q_OBJECT
    
    public:
        enum Roles {
            Role1 = Qt::UserRole + 1,
            Role2,
            Role3
        };
    
        MyModel(QObject *parent = nullptr);
    
        Q_INVOKABLE void addRow(QString str1, QString str2, QString str3);
    
        Q_INVOKABLE int columnCount(const QModelIndex &parent) const;
    
        Q_INVOKABLE int rowCount(const QModelIndex & parent = QModelIndex()) const;
    
        Q_INVOKABLE QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
        //QVariant data(const QModelIndex &index, int role) const;
        QHash<int, QByteArray> roleNames() const;
    
    private:
        QList <QString> list1, list2, list3;
    };
    
    #endif // MYMODEL_H
    
    
    #include "mymodel.h"
    
    MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent)
    {
        list1<<"11"<<"111"<<"1111";
        list2<<"22"<<"222"<<"2222";
        list3<<"33"<<"333"<<"3333";
    }
    
    void MyModel::addRow(QString str1, QString str2, QString str3)
    {
        beginInsertRows( QModelIndex(), 0, 2 );
        list1.append(str1);
        list2.append(str2);
        list3.append(str3);
        endInsertRows();
    }
    
    int MyModel::columnCount(const QModelIndex &parent) const
    {
        return 3;
    }
    
    int MyModel::rowCount(const QModelIndex & parent) const {
        Q_UNUSED(parent);
        return list1.count();
    }
    
    QVariant MyModel::data(const QModelIndex & index, int role) const {
        if (index.row() < 0 || index.row() >= list1.count())
            return QVariant();
    
        qDebug()<<index.column()<<index.row();
    
        QString unswer = QString("row = ") + QString::number(index.row()) + "  col = " + QString::number(index.column());
        // строкой выше мы формируем ответ. QString::number преобразует число в текст
        return QVariant(unswer);
    
    //    return QString("Row%1, Column%2")
    //                       .arg(index.row() + 1)
    //                       .arg(index.column() +1);
    
        if(index.column() == 0){
            return list1[index.row()];
        }
        if(index.column() == 1){
            return list2[index.row()];
        }
        if(index.column() == 2){
            return list3[index.row()];
        }
        return QVariant();
    }
    
    QHash<int, QByteArray> MyModel::roleNames() const {
        QHash<int, QByteArray> roles;
        roles[Role1] = "role1";
        roles[Role2] = "role2";
        roles[Role3] = "role3";
        return roles;
    }
    
    

  • Qt Champions 2019

    @Mikeeeeee said in The model inherited from QAbstractTableModel throws errors:

    What is the bug and how to fix it?

    Christian Ehrlicher 18 minutes ago

    And you should only return values for Qt::DisplayRole



  • I fixed the code, there is no more error. But the column index is always zero. I don't understand how to fix this. Debag returns:
    0 0
    0 0
    0 0
    Model size of -3 is less than 0
    0 1
    0 1
    0 1
    0 2
    0 2
    0 2



  • 1.png


  • Qt Champions 2019

    @Mikeeeeee said in The model inherited from QAbstractTableModel throws errors:

    I fixed the code

    Please update your code in your example so we can see what you're doing.



  • This post is deleted!


  • @Christian-Ehrlicher I updated the code an hour ago. I didn't add anything after that.



  • Maybe the problem is in QML?

    import QtQuick 2.13
    import QtQuick.Controls 1.4
    
    Item {
        width: 380
        height: 680
    
        TableView {
            anchors.fill: parent
            TableViewColumn {
                role: "role1"
                title: "Column1"
                width: 100
            }
            TableViewColumn {
                role: "role2"
                title: "Column2"
                width: 100
            }
            TableViewColumn {
                role: "role3"
                title: "Column3"
                width: 100
            }
            model: myModel
        }
    
    }
    

  • Qt Champions 2019

    Then you still did not read my comment about the Qt::DisplayRole. So stay on your own.



  • I don't understand what you mean. Please answer in more detail and clearly.



  • Its work

    QVariant MyModel::data(const QModelIndex & index, int role) const {
        if (index.row() < 0 || index.row() >= list1.count())
            return QVariant();
        if(role == 0){
            return QVariant(list1[index.row()]);
        }
        if(role == 1){
            return QVariant(list2[index.row()]);
        }
        if(role == 2){
            return QVariant(list3[index.row()]);
        }
        return QVariant();
    }
    

Log in to reply