1、实现效果
2、源码
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QAbstractListModel>
#include <QStringList>
//简单的、非层次结构的数据模型
class Widget : public QAbstractListModel
{
Q_OBJECT
public:
Widget(const QStringList &strings, QObject *parent = 0);
~Widget();
//非层次结构,不需要考虑父子关系
//如果模型是层次结构的,还需要实现index()和parent()函数
//只读模型,需要实现的函数
int rowCount(const QModelIndex &parent = QModelIndex()) const override;//返回模型行数
QVariant data(const QModelIndex &index, int role) const override;//返回指定模型索引的数据项
//在树和表格视图的标头显示一些内容
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
//将各种操作转换为对具体数据源的操作,从而对外提供一个统一的接口
//实现界面可编辑,需要实现的函数
//模型让委托知道项目是可编辑的,这里为每个项目返回一个正确的标识
Qt::ItemFlags flags(const QModelIndex &index) const override;
//为委托向模型中设置数据提供一条途径
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
//实现在模型中插入和删除行,需要实现的函数
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
private:
//QAbstractItemModel本身不存储任何数据,仅提供一些接口来供视图访问数据
//string_list_作为内部数据源
QStringList string_list_;
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
Widget::Widget(const QStringList &strings, QObject *parent)
: QAbstractListModel(parent), string_list_(strings)
{
}
Widget::~Widget()
{
}
int Widget::rowCount(const QModelIndex &parent) const
{
return string_list_.count();
}
QVariant Widget::data(const QModelIndex &index, int role) const
{
if(!index.isValid()){
return QVariant();
}
if(index.row() >= string_list_.size()){
return QVariant();
}
if(role == Qt::DisplayRole || role == Qt::EditRole){
return string_list_.at(index.row());
}else {
return QVariant();
}
}
QVariant Widget::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role != Qt::DisplayRole){
return QVariant();
}
if(orientation == Qt::Horizontal){
return QString("Column %1").arg(section);
}else {
return QString("Row %1").arg(section);
}
}
Qt::ItemFlags Widget::flags(const QModelIndex &index) const
{
if(!index.isValid()){
return Qt::ItemIsEnabled;
}
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
bool Widget::setData(const QModelIndex &index, const QVariant &value, int role)
{
//保证索引是有效的、项目是正确的类型、角色是被支持的
if(index.isValid() && role == Qt::EditRole){
string_list_.replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return false;
}
bool Widget::insertRows(int position, int rows, const QModelIndex &index)
{
//告知其他组件指定的行将要发生改变
beginInsertRows(QModelIndex(), position, position + rows -1);//父项的模型索引,要插入的第一个、最后一个新行的行号
for(int row = 0; row < rows; ++row){
string_list_.insert(position, "");//添加空的字符串
}
//告知其他组件该模型大小发生了变化
endInsertRows();
return true;
}
bool Widget::removeRows(int position, int rows, const QModelIndex &index)
{
beginRemoveRows(QModelIndex(), position, position + rows -1);
for(int row = 0; row < rows; ++row){
string_list_.removeAt(position);
}
endRemoveRows();
return true;
}
//main.cpp
#include "widget.h"
#include <QApplication>
#include <QTableView>
#include <QListView>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList list;
list << "a" << "b" << "c";
Widget model(list);
QListView listView;
listView.setModel(&model);
listView.show();
QTableView tableView;
tableView.setModel(&model);
tableView.show();
//添加和删除
model.insertRows(3,2);
model.removeRows(0,1);
return a.exec();
}