ndex(row, column);
}
QModelIndex 无法直接访问其成员,要产生索引请调用 createIndex 方法。
实现 data 方法。返回数据,这里咱们实现了正常显示的文本和作为工具提示用的文本。
QVariant MyItemModel::data(const QModelIndex &index, int role) const
{
// 注意 role 这个参数,返回前必须判断
if(role == Qt::DisplayRole)
{
// DisplayRole 说明获取的数据是用在界面呈现上的
// 咱们只考虑行号,列号嘛,反正只有一列
int idx = index.row();
return m_list.at(idx);
}
// 可以提供工具提示
if(role == Qt::ToolTipRole)
{
int i = index.row();
int val = m_list.at(i);
return QString("这是整数值:%1").arg(val);
}
// 如果是其他role,就返回一个默认的QVariant给它
return QVariant();
}
其他未用到的数据角色返回空的 QVariant 就可以。data 方法返回的值,是对应着二维表中某个单元格的,所以,你希望在那个单元格中显示什么就返回什么。
最后实现的两个方法是用来获取或设置数据源的(即原始数据)。
QList<int> MyItemModel::intList() const
{
return m_list;
}
void MyItemModel::setIntList(const QList<int> &list)
{
m_list = list;
}
至此,一个简单的模型就有了,当然,没有实现 setData 方法,它只能读数据,不支持编辑。现在我们可以拿来用了。
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// 创建视图实例
QListView lv;
lv.setWindowTitle("简单模型");
// 准备点数据
QList<int> theList;
theList << 100 << 300 << 4500 << 600 << 1200;
// 实例化模型
MyItemModel *model;
model = new MyItemModel(theList);
//model->setIntList(theList);
// 为视图设置模型
lv.setModel(model);
// 显示窗口
lv.show();
// 主循环
return QApplication::exec();
}
QListView 作为视图组件,适合显示简单的列表。调用视图的 setModel 方法就可以关联指定的模型对象了。如上述代码中,咱们自定义的 MyItemModel 在设置了原始数据后,就可以传递给 setModel 方法以提供数据。
结果如下图所示:
把鼠标移到某个项上,还能看到工具提示呢。
咱们给 MyItemModel 加上 setData 方法的重写,使它支持编辑功能。
// 头文件
bool setData(const QModelIndex &index, const QVariant &value, int
role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
// 实现代码
bool MyItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// 设置数据时数据角色通常是编辑
if(role == Qt::EditRole)
{
// 因为只有一列,我们不用关心列号,只取行号
int row = index.row();
if(value.canConvert<int>() == false)
{
// 不是int值,玩不下去了
return false;
}
// 更新数据
m_list.replace(row, value.toInt());
// 发出信号
QList<int> roles = { Qt::DisplayRole, Qt::EditRole, Qt::ToolTipRole };
emit dataChanged(index, index, roles);
// 输出一下,主要是检查list有没有顺利修改
qDebug() << m_list;
return true;
}
return false;
}
Qt::ItemFlags MyItemModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags oldFlags = QAbstractItemModel::flags(index);
return oldFlags | Qt::ItemIsEditable;
}
先说说为什么要同时重写 flags 方法,此方法返回 ItemFlag 枚举的值(值可以合并)。如果想让视图组件知道此模型允许编辑,那么返回的 ItemFlags 必须包含 ItemEditable 值。
现在说 setData 方法。首先,role 参数得是 EditRole 才表明用户界面已进入编辑状态,并且这个值是在编辑状态下传送过来的。canConvert 方法是检查一下传过来的是不是 int 值,这里如果是 QListView 组件默认处理的话,一般不会搞错类型。
咱们的原始数据就是存放在 QList<int> 对象中的,所以只调用 replace 方法把某个索引处的值替换下就可以了;如果数据来自文件,就得写入文件以保存。
在数据更新后,记得发送一个 dataChanged 信号,通知所有连接到此信号的对象,数据已变更,赶紧刷新提取最更的值。dataChanged 信号需要三个参数:
void dataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight,
const QList<int> &roles = QList<int>());
topLeft 参数和 bottomRight 参数是两个索引,它们描述了被修动数据的区域,用左上角和右下角的索引来表示。本示例中,每次只修改一个行,所以,左上角和右下角的索引都是被修改项的索引。roles 参数告诉程序:哪些角色的数要更新一下。一般 EditRole 和 DisplayRole 的要更新,这样可让应用程序知道去刷新数据。模型只用在 QListView 视图中,所以就算不发出 dataChanged 信号,组件也能自动刷新。但如果模型同时应用在多个视图中,并且有其他代码连接了 dataChanged 信号,那就得发出这个信号了。
setData 方法返回 bo