Qt 继承QAbstractListModel实现自定义ListModel

1.简介

QAbstractListModel类提供了一个抽象模型,可以将其子类化以创建一维列表模型。

QAbstractListModel为将其数据表示为简单的非层次项目序列的模型提供了一个标准接口。它不直接使用,但必须进行子类化。

由于该模型提供了比QAbstractItemModel更专业的接口,因此不适合与树视图一起使用;如果您想提供一个用于此目的的模型,则需要对QAbstractItemModel进行子类化。如果您需要使用多个列表模型来管理数据,则可能更适合使用子类QAbstractTableModel。

继承QAbstractListModel,需要重写rowCount()、data()、insertRows()、removeRows()等函数。

  • rowCount()函数返回模型的行数。
  • data()函数返回指定索引处的数据。
  • insertRows()插入行
  • removeRows()删除行

2.示例

cpp 复制代码
#ifndef MYLISTMODEL_H
#define MYLISTMODEL_H

#include <QAbstractListModel>
#include <QObject>
#include <QList>

typedef struct _student
{
    QString name;
    int age;
    double score;
}Student;

class MyListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    MyListModel(QObject *parent = nullptr);

    enum RoleNames{
        Name,
        Age,
        Score
    };

public:
    //更新
    void update(QList<Student> students);

    // 返回列表中行的数量
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;

    // 返回指定索引处的数据
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

    //插入行
    virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());

    //删除行
    virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());

private:
    QList<Student> m_lstStu;
};

#endif // MYLISTMODEL_H


#include "MyListModel.h"

MyListModel::MyListModel(QObject *parent)
    : QAbstractListModel(parent)
{

}

void MyListModel::update(QList<Student> students)
{
    m_lstStu = students;
    for(int i=0;i<m_lstStu.size();i++)
    {
        beginInsertRows(QModelIndex(),i,i);
        endInsertRows();
    }
}

int MyListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_lstStu.size();
}


QVariant MyListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    int nRow = index.row();
    Student stu = m_lstStu.at(nRow);

    if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
        QString ret = QString("%1_%2_%3").arg(stu.name)
                .arg(stu.age).arg(stu.score);

        return ret;
    }

    return QVariant();
}

bool MyListModel::insertRows(int row, int count, const QModelIndex &parent)
{
    if (row >= 0 && row <= m_lstStu.size())
    {
        beginInsertRows(parent, row, row + count - 1);
        for (int i = 0; i < count; ++i)
        {
            //插入一个空的数据
            Student stu;
            stu.name = QString();
            stu.age = 0;
            stu.score = 0;
            m_lstStu.insert(row, stu);
        }
        endInsertRows();
        return true;
    }
    return false;
}


bool MyListModel::removeRows(int row, int count, const QModelIndex &parent)
{
    if (row >= 0 && row + count <= m_lstStu.size())
    {
        beginRemoveRows(parent, row, row + count - 1);
        for (int i = 0; i < count; ++i)
        {
            m_lstStu.removeAt(row);
        }
        endRemoveRows();
        return true;
    }
    return false;
}

使用:

cpp 复制代码
#include "ListForm.h"
#include "ui_ListForm.h"
#include "MyListModel.h"

MyListModel *pModel = nullptr;

ListForm::ListForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ListForm)
{
    ui->setupUi(this);

    //去除选中虚线框
    ui->listView->setFocusPolicy(Qt::NoFocus);

    //设置整行选中
    ui->listView->setSelectionBehavior(QAbstractItemView::SelectRows);

    pModel = new MyListModel(this);

    // 构造数据,更新界面
    QList<Student> students;
    QList<QString> nameList;
    nameList<<"张三"<<"李四"<<"王二"<<"赵五"<<"刘六";

    for (int i = 0; i < 5; ++i)
    {
        Student student;
        student.name = nameList.at(i);
        student.age = qrand()%6 + 13;//随机生成13到19的随机数
        student.score = qrand()%20 + 80;//随机生成0到100的随机数;

        students.append(student);
    }

    pModel->update(students);
    ui->listView->setModel(pModel);
}

ListForm::~ListForm()
{
    delete ui;
}

void ListForm::on_btnInsert_clicked()
{
    if(!pModel)
        return;

    int row = ui->listView->currentIndex().row();

    if(row < 0)
        return;

    pModel->insertRows(row+1,1);
}

void ListForm::on_btnDel_clicked()
{
    if(!pModel)
        return;

    int row = ui->listView->currentIndex().row();

    if(row < 0)
        return;

    pModel->removeRows(row,1);
}
相关推荐
----云烟----4 小时前
QT中QString类的各种使用
开发语言·qt
「QT(C++)开发工程师」9 小时前
【qt版本概述】
开发语言·qt
一路冰雨13 小时前
Qt打开文件对话框选择文件之后弹出两次
开发语言·qt
老赵的博客14 小时前
QT 自定义界面布局要诀
开发语言·qt
码码哈哈0.014 小时前
VSCode 2022 离线安装插件QT VSTOOl报错此扩展不能安装在任何当前安装的产品上。
ide·vscode·qt
feiyangqingyun18 小时前
Qt/C++离线地图的加载和交互/可以离线使用/百度和天地图离线/支持手机上运行
c++·qt·qt天地图·qt离线地图·qt地图导航
gz94561 天前
windows下,用CMake编译qt项目,出现错误By not providing “FindQt5.cmake“...
开发语言·qt
「QT(C++)开发工程师」1 天前
Ubuntu 26.04 LTS 大升级:Qt 6 成为未来新引擎
qt
兆。1 天前
python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具
爬虫·python·qt
喝哈喝哈2 天前
pycharm中配置pyqt5
python·qt·pycharm