自定义数据模型

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();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值