Qt学习笔记-----ModelView架构之自定义Model

    xiaoxiao2021-03-25  55

    作者:一个程序渣渣的小后院 地址:http://blog.csdn.net/sinat_35261315/article/details/54849486

    Model/View Framework中提供了模型model的抽象基类QAbstractItemModel, 如果需要自定义模型就需要继承这个类并且实现一些必要的函数。  此外,Qt中又提供了QAbstractTableModel和QAbstractListModel分别继承于上述基类,由名字可以清楚的知道这两个类分别适用于表格模型和列表模型。对于这两个模型来说,很多函数已经重新实现过了,使用时直接继承即可。

    QAbstractItemModel  QAbstractItemModel为元素模型类提供了抽象接口,自定义模型时需要继承这个类。自定义的模型分为只读模型和可编辑模型。

    只读模型:内部数据不能修改  为了实现一个只读模型,需要重新实现以下函数:

    flags

    Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const 1 1

    这个函数返回被给模型索引index的标志,用于其他组件获得每一个元素的信息。在很多模型中,返回的flags应该包括Qt::ItemIsEnabled和Qt::ItemIsSelectable,表示模型中的元素是可以被访问和选择的。通常实现的形式为:

    if(!index.isValid()) return Qt::ItemIsEnabled; return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable; 123 123

    data

    QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const 1 1

    这个函数返回模型索引index的底层数据(一个模型索引包括某一元素的信息,包括行,列,以及数据),用于视图和委托访问数据。通常的实现形式如下:

    if(!index.isValid()) return QVariant(); if(index.row() >= /*数据总个数*/) return QVariant(); if(role == Qt::DisplayRole) { int row = index.row(); int column = index.column(); //根据模型存储数据所用的数据结构来返回对应行和列的数据 return /*数据*/ } return QVariant(); 123456789101112 123456789101112

    headerData

    QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role == Qt::DisplayRole) const 1 1

    这个函数返回某部分对应方向上的表头,为Views提供显示在Views顶部(即最上方和最左边)的标识。通常实现形式为:

    if(role != Qt::DisplayRole) return QVariant(); if(orientation == Qt::Horizontal)//headersData在最上方,水平方向 或if(orientation == Qt::Vertical) //headersData在最左边,垂直方向 { //判断section,section表示的是第几个 return ... } return QVariant(); 123456789 123456789

    rowCount

    int QAbstractItemModel::rowCount(const QModelIndex &parent = QModelIndex()) const 1 1

    这个函数返回被给的模型索引下有多少行,返回的是parent的孩子数。而不是整个行数。如果没有子元素,则返回0。

    对于继承于QAbstractListModel的类来说,只需要重新实现这四个函数。而对于继承于QAbstractTableModel和QAbstractItemModel的类来说,除了上述四个函数,还需要重新实现columnCount函数,因为列表只有1列,而表格和树则需要自定义:

    columnCount

    int QAbstractItemModel::columnCount(const QModelIndex &parent = QModelIndex()) const 1 1

    这个函数通常与给定的parent无关,所涉及的类有几列就返回几。

    可编辑模型:允许数据被修改,也可以允许插入和删除操作。

    实现可编辑模型,除了上述只读模型的函数外,还需要重新实现以下函数:

    flags

    Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const 1 1

    这个函数和只读模型的函数一样,只是返回时需要增加Qt::ItemIsEditable,形式如下:

    if(!index.isValid()) return Qt::ItemIsEnabled; return QAbstractItemModel::flags(index) | Qt::ItemIsEditabled; 123 123

    setData

    bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) 1 1

    data函数用来获取数据,setData函数用来设置模型索引index中存储的数据,形式如下:

    if(index.isValid() && role == EditRole) { int row = index.row(); //根据行号从内部数据结构中定位,然后将其改编成value emit dataChanged(index, index); return true; } return false; 12345678 12345678

    另外需要注意的是,在改变完内部数据后,需要发出dataChanged(index, index)信号通知Views和Delegate内部数据已经发生改变。

    setHeaderData

    bool QAbstractItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) 1 1

    headerData函数用于返回表头,这个函数设置表头为value,形式如下:

    if(role != EditRole) return false; if(orientation == Qt::Horizontal) 或 if(orientation == Qt::Vertical) { //改变存储表头的变量 emit headerDataChanged(orientation, section, section); return true; } return false; 123456789 123456789

    同样,当改变表头后,需要发出headerDataChanged(orientation, section, section)信号,通知Views和Delegate。

    如果需要添加和删除操作,则需要实现以下函数:  insertRows

    bool QAbstractItemModel::insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) 1 1

    这个函数在父级为index的结构中的第position行插入rows行。形式如下:

    beginInsertRows(index, position, position + rows - 1); //内部变量进行删除操作 endInsertRows(); return true; 12345 12345

    进行插入操作时,前后分别需要调用beginInsertRows()和endInsertRows()函数。

    removeRows

    bool QAbstractItemModel::removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) 1 1

    这个函数在父级为index的结构中的第position行删除rows行。形式如下:

    beginRemoveRows(index, position, position + rows - 1); //内部变量进行删除操作 endRemoveRows(); return true; 1234 1234

    进行删除操作时,前后需要调用beginRemoveRows()和endRemoveRows()函数。

    insertColumns  removeColumns  这两个函数同插入行和删除行类似,也需要调用两个函数。

    通常情况下,函数应该返回true如果操作成功,但是如果只是部分操作成功,例如只插入了部分行,则需要返回false。

    例子:http://qimo601.iteye.com/blog/1534331
    转载请注明原文地址: https://ju.6miu.com/read-36345.html

    最新回复(0)