QStandardItemModel&绑定到自定义对象 [英] QStandardItemModel & binding to custom object
问题描述
我尝试使用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::DisplayRole
的role
时,在我们的示例中,该函数应返回将显示在(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&绑定到自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!