QStandardItemModel&绑定到自定义对象 [英] QStandardItemModel & binding to custom object

查看:221
本文介绍了QStandardItemModel&绑定到自定义对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用Qt示例的city-standarditem并使其适应我的示例.我得到一个奇怪的结果:

I tried to use the cities-standarditem of the Qt exemple and adapt it to my exemple. I have a strange result:

这是我的用户类别:

class User{
public:
User();

QString getFirstname() const;
void setFirstname(const QString &value);

QString getLastname() const;
void setLastname(const QString &value);

int getAge() const;
void setAge(int value);

private:
QString firstname;
QString lastname;
int age;
};

我已经声明了一个usermodel.h:

and i have declared a usermodel.h:

class UserModel: public QStandardItemModel
{
    Q_OBJECT
public:
    UserModel(QList<User> users, QObject *parent = Q_NULLPTR);

    QHash<int, QByteArray> roleNames() const;
};

这是构造函数和roleNames函数的实现:

And here is the implementations of the constructor and the roleNames functions:

enum ItemRoles {
    FirstnameRole,
    LastnameRole,
    AgeRole,
};


UserModel::UserModel(QList<User> users, QObject *parent) : QStandardItemModel(parent)
{    

    //this->setItemRoleNames(roleNames());
    this->setColumnCount(3);
    for (auto user: users) {
        QStandardItem *item = new QStandardItem();
        item->setData(user.getFirstname(), FirstnameRole);
        item->setData(user.getLastname(), LastnameRole);
        item->setData(user.getAge(), AgeRole);
        appendRow(item);
    }

    setSortRole(FirstnameRole);
}


QHash<int, QByteArray> UserModel::roleNames() const
{
    QHash<int, QByteArray> mapping = QStandardItemModel::roleNames();

    mapping[FirstnameRole] = "firstname";
    mapping[LastnameRole] = "lastname";
    mapping[AgeRole] = "age";

    return mapping;
}

我的表格视图仅显示该函数添加的最后一个角色: item->setData(user.getFirstname(), FirstnameRole);

My table view only show the last Role added with the function: item->setData(user.getFirstname(), FirstnameRole);

如果最后加上年龄,则表明年龄... 有任何线索吗?

If its the age lastly added, its the age showed... Any clues ?

推荐答案

假设您确实需要一个自定义模型,并希望扩展现有模型.由于您的数据采用表格形式,因此建议您使用QAbstractTableModel作为基类.

Let's say you really need a custom model and want to extend an existing one. Since your data is in tabular fashion, I'd suggest to use QAbstractTableModel as the base class.

让我们上这个课:

class UserModel: public QAbstractTableModel
{
    Q_OBJECT
    QList<User> _users;
public:
    UserModel(QList<User> users, QObject *parent = Q_NULLPTR) : QAbstractTableModel(parent), _users(users){}

如您所见,类本身存储了在构建时给出的用户列表.构造函数本身只做复制列表初始化操作.

As you can see, the class itself stores a list of users, given at construction time. The constructor itself does nothing but copy-initializing the list.

那么您至少需要提供以下实现:

Then you need to supply these implementation, at least:

int rowCount(const QModelIndex &) const override
{
    return _users.size();
}
int columnCount(const QModelIndex &) const override
{
    return 3;
}
QVariant data(const QModelIndex &index, int role) const override
{
    if(role == Qt::DisplayRole)
    {
        User user = _users.at(index.row());
        QVariant data[] = { user.getFirstname(), user.getLastname() , user.getAge() };
        return data[index.column()];
    }
    return {};
}

columnCount为常数且始终返回3时,rowCount将返回用户列表中的项目数. 在data实现中,根据索引 row column 以及传递的 role ,检查传递的索引并返回值. . 重要的是要理解,当视图调用data并传递等于Qt::DisplayRolerole时,在我们的示例中,该函数应返回将显示在(index.row(), index.column())单元格中的数据,这是三个中的一个User的数据成员.

While columnCount is constant and always returns 3, rowCount will return the number of items in the list of users. In data implementation, the index passed is inspected and a value is returned, according to the index row and column, and the passed role. It's important to understand that when the view calls data passing a role equal to Qt::DisplayRole, the function should return the very data that will be shown in the cell at (index.row(), index.column()), in our case: one of the three User's data members.

重新实现sort功能也非常有用,即

It's quite useful to reimplement the sort function as well, i.e.

void sort(int column, Qt::SortOrder order) override
{
    auto fnSort = [](const User & u1, const User & u2){ return u1.getFirstname() < u2.getFirstname(); };
    auto lnSort = [](const User & u1, const User & u2){ return u1.getLastname() < u2.getLastname(); };
    auto agSort = [](const User & u1, const User & u2){ return u1.getAge() < u2.getAge(); };

    std::function<bool (const User &, const User &)>  sortFn[] = {fnSort, lnSort, agSort};
    std::sort(_users.begin(), _users.end(), sortFn[column]);

    if(order == Qt::DescendingOrder)
    {
        std::reverse(_users.begin(), _users.end());
    }
}

这样,您可以按预期方式让用户按列排序:

This way you let the user sort by column, as expected:

myTableView->setModel(new UserModel(list));
myTableView->model()->sort(2, Qt::DescendingOrder); //sort by first age, in descending order

如果由于某种原因您想使用 custom 角色,请让您的枚举像这样:

If, for some reason, you want to use custom roles, please have your enum be like this:

enum ItemRoles {
    FirstnameRole = Qt::UserRole,
    LastnameRole,
    AgeRole,
};

Qt::UserRole开始(用于此目的)可确保您的角色不会与其他内置角色发生冲突.

Starting from Qt::UserRole (which is there for this very purpose) ensures that your roles don't clash whit builtin roles.

请注意,上面的代码旨在建议一种可能的解决方案,而不是 解决方案本身(并且缺少许多重要功能,例如边界检查和内存管理).

Please notice that the above code is meant to suggest a possible solution and it's not the solution itself (and lacks many important features like bounds checking and memory management).

这篇关于QStandardItemModel&amp;绑定到自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆