简体   繁体   中英

Data is not displayed in TableView

I try to build simple TableView with model from C++. My table has as many rows and columns, as return rowCount and columnCount method. This means, model is 'connected' with view, but in each cell does not display the message: 'Some data'

here is my code:

class PlaylistModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    PlaylistModel(QObject *parent=0): QAbstractTableModel(parent), rows(0){}

    int rowCount(const QModelIndex & /*parent*/) const
    {
        return 5;
    }
    int columnCount(const QModelIndex & /*parent*/) const
    {
        return 3;
    }
    QModelIndex index(int row, int column, const QModelIndex &parent) const {
         return createIndex(row, column);
    }
    QModelIndex parent(const QModelIndex &child) const {
         return child.parent();
    }
    QVariant data(const QModelIndex &index, int role) const{
        if (role == Qt::DisplayRole)
             {
               return QString("Some data");
             }
        return QVariant();
    }
(...)
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
PlaylistModel plModel(0);
engine.rootContext()->setContextProperty("myModel", &plModel);
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

and qml

TableView {
                id: trackList
                width: 100; height: 100
                model: myModel
                TableViewColumn { role: "id"; title: "Id"; width: 30 }
                TableViewColumn { role: "name"; title: "Name"; width: 100}
                TableViewColumn { role: "duration"; title: "Duration"; width: 20 }

            }

Where I make a mistake?

Short answer

Because your QML is not asking for Qt::DisplayRole . Change your TableVievColumn to

TableViewColumn { role: "display"; title: "xxx"; width: 20 }

The QML is now asking for Qt::DisplayRole , and "Some data" is shown in this column.

Long answer

QML is asking for three user-defined roles: "id", "name", and "duration". However, the three roles are not bulit-in roles. Therefore you need to implement the three roles in your model class.

First, you should provide a set of roles to the model. The model returns data to views using QAbstractItemModel::data function. The type of role is int, we can write an enum in the model class:

class PlaylistModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    enum MyTableRoles 
    {
        IdRole = Qt::UserRole + 1,
        NameRole,
        DurationRole
    }
    //...
};

Now, in the data function, returns the corresponding value any time the view is asking:

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

    switch(role)
    {
    case IdRole:
        return GetIdFromMyTable(index);
    case NameRole:
        return GetNameFromMyTable(index);
    case DurationRole:
        return GetDurationFromMyTable(index);
    }
    //...
    return QVariant();
}

Next, provide a string-to-int mapping for each role. The role in the model is in type of int, however in the QML the role is type of string. (see the role property in TableViewColumn .) Therefore we should provide a string-to-int mapping for each role so the QML can correctly asking for the required data. The mapping should be provided in QAbstractItemModel::roleNames() :

QHash<int, QByteArray> PlaylistModel::roleNames() const
{
    QHash<int, QByteArray> roleNameMap;
    roleNameMap[IdRole] = "id";
    roleNameMap[NameRole] = "name";
    roleNameMap[DurationRole] = "duration";

    return roleNameMap;
}

Finally your table in QML now can display the things you want.

Some references

When subclassing QAbstractTableModel ,

you must implement rowCount(), columnCount(), and data(). Default implementations of the index() and parent() functions are provided by QAbstractTableModel.

When using C++ models in QML ,

The roles of a QAbstractItemModel subclass can be exposed to QML by reimplementing QAbstractItemModel::roleNames().

And if you do not reimplement the roleNames function, you can use only the default roles declared in QAbstractItemModel::roleNames . And this is the reason why the short answer works.

You did not implemented index method.

According to documentation,

When subclassing QAbstractItemModel, at the very least you must implement index() , parent(), rowCount(), columnCount(), and data(). These functions are used in all read-only models, and form the basis of editable models.

in other words, You have to implement your own low-level item management, AbstractItemModel will not do it for you. You should create indexes with createIndex and destroy them when nesessary etc.

If you don't want to play these games and just want to implement your own quick&dirty model, consider subclassing QStandardItemModel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM