Qt模型视图框架(二)

简介: Qt模型视图框架(二)

在上一篇文章中,已经对Qt模型视图框架有了一个大致的了解,这篇文章我们主要来看一下模型基类QStandardItemModel的用法。

一般地,使用QStandardItemModel作为数据模型已经足够满足我们的需求了。这是因为它实现了QAbstractItemModel接口,这意味着该模型可以为任何支持该接口的视图中提供数据(例如QListView、QTableView和QTreeView,以及您自己的自定义视图)。

对于性能和灵活性,您可能想要子类化QAbstractItemModel来为不同类型的数据存储库提供支持。例如,QDirModel为底层文件系统提供了一个模型接口。

QStandardItemModel使用QStandardItem作为数据支撑。

1 QStandardItemModel常用方法介绍:

对于数据的操作,无非就是增删改查,我们就以这四个方面来对QStandardItemModel的方法进行介绍,因为QStandardItem是单个数据项的载体,所以这里我们只要能获取QStandardItem就可以很容易的获取数据。以下的数据操作,均指操作QStandardItem。

1.1 查询数据

1.1.1 item(int row, int column = 0) const

该接口可根据行号和列号返回QStandardItem指针。如果是一个树视图,通过这个接口,只能获取顶层item。想要获取下一分支的item可以使用QStandardItem的child接口。

1.1.2 invisibleRootItem() const

对于每个顶层item,其实它都是一个不可见item的子item,如果想要便利所有顶层item,可以使用如下方法。

QStandardItemModel* model = new QStandardItemModel;
QStandardItem* rootItem = model->invisibleRootItem();
for (int i = 0; i < rootItem->rowCount(); ++i)
{
    for (int j = 0; j < rootItem->columnCount(); ++j)
    {
        QStandardItem* item = rootItem->child(i, j);
        //do somting ... 
    }
}


当然,你也可以使用QStandardItemModel::rowCount和QStandardItemModel::columnCount来遍历顶层item,但如果你是递归遍历一棵树时,应该使用invisibleRootItem()的方法来遍历,因为这会为你遍历树提供一个统一的方法。否则你必须编写两个方法。

1.1.3 itemFromIndex(const QModelIndex &index) const

通过QModelIndex来获取item,QModelIndex 是一个用于定位item的类,关于这个类我会在后面的文章专门介绍。而且这个接口也是经常使用的,所以你最好记住它。

1.1.4 rowCount和columnCount可分别获取行数和列数

1.1.5 data(const QModelIndex &index, int role = Qt::DisplayRole) const

这个接口非常重要,它可以根据QModelIndex获取item中保存的数据,这对于快速检索出item所代表的数据是非常有用的。

因为一个item可以代表很多不同类型的数据,那么我们可以根据role这个参数来获取该item对应的某类数据,这里的默认参数是DisplayRole,即表示获取item其本身显示的数据。当然,如果你传递一个Qt::ToolTipRole,那么它将返回一个提示信息对应的数据。如果你想获取用户自定义类型,那么可以传递一个int类型,但这个类型要不小于Qt::UserRole。

data接口返回一个QVariant类型,这表明在item中可以存储QString,int,bool,Point,QRect,QVector3D等,也支持用户自定义类型,但你必须要先使用Q_DECLARE_METATYPE宏来向元对象系统进行注册声明。

与data接口相对应的是setData,用来设置数据。

1.1.6 findItems(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly, int column = 0) const

返回在给定列中使用给定标志匹配给定文本的item列表。

1.2 添加数据

1.2.1 appendRow(QStandardItem *item)

添加数据到模型的最后一行,与其相同的有insertRow(),insertColumn()。

该接口的另一个重载形式是appendRow(const QList&items) 其参数是一个QList列表,如果所使用的视图是一个table或者是一个tree,则该列表表示一行数据中的多列数据。

1.2.2 setRowCount(int) ,setColumnCount(int)

设置行数, 设置列数

1.3 修改数据

1.3.1 setItem(int row, int column, QStandardItem *item)

将item放置到表中

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

设置index对应的item数据

1.4 删除数据

1.4.1 clear()

从模型中删除所有项。

1.4.2 removeRow()或removeColumn()

删除行,删除列。 在删除多行数据时,一定要注意索引问题。 请看一个删除文本为“apple”的程序

for (int i = 0; i < model->rowCount(); ++i)
{
    QStandardItem* item = model->item(i);
    if (item->text() == "apple")
    {
        model->removeRow(i);
    }
}


如果,这个列表中包含有多个有apple的item,则执行这部分代码时,程序不能正确的删除所有apple项。 不知道你有没有看出来,当从model中第一次删除了文本为"apple"的item后,model的行数就少了一行,且其后一项的索引自动的减一,当下一次再删除apple项时,很可能就跳过了apple项。

为了解决这个问题,可以使用倒叙的方法,即从列表的最后一项起,向前删除item,这是一个很不错的想法,而且也很实用。

你也可以使用findItme找出所有符合条件的item,然后删除它们。

2 示例程序

standarditemmodelwidget.h

#ifndef STANDARDITEMMODELWIDGET_H
#define STANDARDITEMMODELWIDGET_H
#include <QWidget>
class StandardItemModelWidget : public QWidget
{
    Q_OBJECT
public:
    StandardItemModelWidget(QWidget *parent = 0);
};
#endif // STANDARDITEMMODELWIDGET_H


standarditemmodelwidget.cpp

#include "standarditemmodelwidget.h"
#include <QDebug>
#include <QPushButton>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QListView>
#include <QWidget>
StandardItemModelWidget::StandardItemModelWidget(QWidget *parent) :
    QWidget(parent)
{
    //创建界面
    QVBoxLayout* layout = new QVBoxLayout(this);
    QStandardItemModel* model = new QStandardItemModel;
    QListView* view = new QListView;
    view->setModel(model);
    layout->addWidget(view);
    //向model中添加数据
    QStringList textList;
    textList << "apple 1" << "apple 2" << "orange" << "banana" << "apple 3" << "red apple";
    for(auto& text: textList)
    {
        QStandardItem *item = new QStandardItem(text);
        model->appendRow(item);
        item->setEditable(false);//设置每个item为不可编辑
    }
    //检索所有的包含apple的数据项
    const int customRole = Qt::UserRole;
    QList<QStandardItem*> appleItems = model->findItems("apple", Qt::MatchContains);
    foreach (QStandardItem* appleItem, appleItems)
    {
        //为apple项设置一个随机生成的颜色图标
        QPixmap pixmap(25,25);
        QColor clr(qrand()%255, qrand()%255, qrand()%255);
        pixmap.fill(clr);
        appleItem->setIcon(QIcon(pixmap));
        appleItem->setToolTip(clr.name());
        appleItem->setData(clr.name(), customRole);
    }
    //当点击item时,在控制台输出其保存的颜色值
    connect(view, &QListView::clicked, [=](const QModelIndex &index){
        QStandardItem* item = model->itemFromIndex(index);
        qDebug() << item->data(customRole).toString();
    });
    //点击按钮删除所有apple项
    QPushButton* btn = new QPushButton("删除以apple开头的项");
    layout->addWidget(btn);
    connect(btn, &QPushButton::clicked, [=](){
        QList<QStandardItem*> appleItems = model->findItems("apple", Qt::MatchContains);
        for (int i = appleItems.size()-1; i >= 0; --i)
        {
            model->removeRow(appleItems.at(i)->row());
        }
    });
    resize(200, 400);
}


运行程序:


好了,今天的分享就到这里了,QStandardItemModel在模型中非常重要的,本篇文章只是带你了解了其比较重要的几个接口,关于它的更多用法,还需要你再深入理解。


最后也希望大家多多支持小豆君的创作,关注小豆君的公众号“小豆君Qt分享”,最新文章都会在公众号第一时间发布,也可加入C++\Qt交流群,一起学习。

相关文章
|
2月前
|
开发框架 网络协议 数据库
Qt:构建跨平台应用的强大框架
Qt:构建跨平台应用的强大框架
|
2月前
|
存储
QT图形视图框架绘制曲线图和Smith图
QT图形视图框架绘制曲线图和Smith图
58 0
|
2月前
QT4.7版本的OPENGL的3D旋转模型例子
QT4.7版本的OPENGL的3D旋转模型例子
|
2月前
|
存储 安全 Java
Qt线程池+生产者消费者模型
Qt线程池+生产者消费者模型
71 5
|
2月前
【qt】标准项模型1
【qt】标准项模型
21 0
|
2月前
|
开发框架 自然语言处理 Linux
Qt:构建强大跨平台应用程序的框架
Qt:构建强大跨平台应用程序的框架
|
1月前
|
编译器 C++
(10)Qt对象模型
(10)Qt对象模型
|
2月前
|
监控 数据可视化 Linux
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
|
2月前
|
索引
【qt】标准型模型 下
【qt】标准型模型 下
9 0
|
2月前
【qt】标准项模型2
【qt】标准项模型
9 0