QtCreator 模块/视图编程( 一) 模型类,自定义模型QStringListModel,QStandardItemModel,QFileSystemModel,QSqlQueryModel,

来源:互联网 发布:adele 25 知乎 编辑:程序博客网 时间:2024/05/22 07:03

1 模型/视图架构

1.1 模型

所有的模型都是基于QAbstractItemModel类,这个类定义了一个接口,可以供视图和委托来访问数据。

Qt提供的现成模型:

QStringListModel:用来存储一个简单的QString项目列表

QStandardItemModel:管理复杂的树型结构数据项,每一个数据项可以包含任意数据

QFileSystemModel:提供了本地文件系统中文件和目录的信息

QSqlQueryModel,QSqlTableModel和QSqlRelationalTableModel来访问数据库


1.2 视图

QListView:将模型的数据项显示为一个列表

QTableView:将模型的数据显示成表格

QTreeView:将模型的数据显示在树中


1.3 委托

定制数据的渲染和编辑方式

QStyledItemDelegate:使用当前样式来绘制它的项目,要实现自定义的委托或者要和Qt样式表一起应用时,建议使用它

QItemDelegate:

#include <QApplication>
#include <QFileSystemModel>
#include <QTreeView>
#include <QListView>
int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    //创建文件系统模型
    QFileSystemModel model;
    //指定根目录
    model.setRootPath(QDir::currentPath());
    //创建树形视图
    QTreeView tree;
    //为视图指定模型
    tree.setModel(&model);
    //指定根索引
    tree.setRootIndex(model.index(QDir::currentPath()));
    //创建列表视图
    QListView list;
    list.setModel(&model);
    list.setRootIndex(model.index(QDir::currentPath()));
    tree.show();
    list.show();
    return app.exec();
}
2 模型类

2.1 模型索引(为了确保数据的表示与数据的获取相分离)QModelIndex类提供

QModelIndex是临时引用,随着模型的结构改变而改变,

QPersistentModelIndex:用于长时间的引用

获取数据项的模型索引,必须指定模型的3个属性:行号,列号和父项的模型索引

2.2 行和列

一个模型可以把它看成一个简单的表格来访问,每个数据项可以使用行号和列号来定位

2.3 父项

顶层数据项的父项是QModelIndex()

2.4 项角色

标准的角色由Qt::ItemDataRole来定义

#include <QApplication>
#include <QStandardItemModel>
#include <QTreeView>
#include <QDebug>
#include <QStandardItem>
int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    //创建标准数据项模型
    QStandardItemModel model;
    //获取模型的根项,根项不可见
    QStandardItem * parentItem = model.invisibleRootItem();
    //创建标准项item0,并设置显示文本,图标和工具提示
    QStandardItem *item0 = new QStandardItem;
    item0->setText("A");
    QPixmap pixmap0(50,50);
    pixmap0.fill("red");
    item0->setIcon(pixmap0);
    item0->setToolTip("indexA");
    //就标准项item0作为根的子项
    parentItem->appendRow(item0);
    //就创建的标准项item0,作为新的父项
    parentItem = item0;
    //为item0创建子项
    QStandardItem *item1 = new QStandardItem;
    item1->setText("B");
    QPixmap pixmap1(50,50);
    pixmap1.fill(("blue"));
    item1->setIcon(pixmap1);
    item1->setToolTip("indexB");
    parentItem->appendRow(item1);
    //创建新的标准项,设置文本,图标,工具提示
    QStandardItem *item2 = new QStandardItem;
    QPixmap pixmap2(50,50);
    pixmap2.fill(("green"));
    item2->setData("C",Qt::EditRole);
    item2->setData("indexC",Qt::ToolTipRole);
    item2->setData(QIcon(pixmap2),Qt::DecorationRole);
    parentItem->appendRow(item2);
    QTreeView view;
    view.setModel(&model);
    view.show();
    QModelIndex indexA = model.index(0,0,QModelIndex());
    qDebug() << "indexA row count:" << model.rowCount(indexA);
    QModelIndex indexB = model.index(0,0,indexA);
    qDebug() << "indexB text:" << model.data(indexB,Qt::EditRole).toString();
    qDebug() << "indexB toolTip:"
             << model.data(indexB,Qt::ToolTipRole);
    return app.exec();
}

3 创建新的模型

3.1 创建只读模型

3.1.1 添加新类:StringListModel,基类:QAbstractListModel,继承自QObject

3.1.2 修改stringlistmode.h头文件

因为QAbstractItemMode本身不存储任何数据,只提供了一个访问数据的接口,所以将StringList作为数据源,

public:
    explicit StringListModel(const QStringList &strings,QObject *parent = 0);
    int rowCount(const QModelIndex &parent = QModelIndex()) const;  //返回模型的行数
    QVariant data(const QModelIndex &index, int role) const;    //返回模型的数据项
    //可以在树和表格视图的表头显示一些内容
    QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const;
private:
    QStringList stringList; //作为模块的数据源

添加函数的实现

int StringListModel::rowCount(const QModelIndex &parent) const
{
    return stringList.count();      //返回item的个数
}
//获取索引项对应的数据
QVariant StringListModel::data(const QModelIndex &index, int role) const
{
    if (! index.isValid()) return QVariant();
    if (index.row() >= stringList.size()) return QVariant();
    if (role == Qt::DisplayRole) return stringList.at(index.row());
    else return QVariant();
}
//设置表头对应的数据
QVariant StringListModel::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);
}
main.cpp

int main(int argc,char* argv[]) {
    QApplication app(argc,argv);
    //为模型构造数据
    QStringList list;
    list << "a" << "b" << "c" ;
    StringListModel model(list);
    QListView listView;
    listView.setModel(&model);
    listView.show();
    QTableView tableView;
    tableView.setModel(&model);
    tableView.show();
    return app.exec();
}

3.2 添加编辑功能

添加flags()与setData,flags函数不知道是干什么的?有懂得可以留言下

    Qt::ItemFlags flags(const QModelIndex &index) const;    //
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); //变更数据
实现函数

Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) return Qt::ItemIsEnabled;
    return QAbstractItemModel::flags(index)|Qt::ItemIsEditable;
}
bool StringListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        stringList.replace(index.row(),value.toString());   //更新值
        emit dataChanged(index,index);      //发出数据变更的信号,左上的index,右下的index
        return true;
    }
    return false;
}
修改data()

if (role == Qt::DisplayRole || role == Qt::EditRole) return stringList.at(index.row());

3.3 插入和删除行

需要添加两个函数insertRows和removeRows

    //row位置,count行数,parent父项索引
    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
实现两个函数

bool StringListModel::insertRows(int row, int count, const QModelIndex &parent)
{
    beginInsertRows(QModelIndex(),row,row+count-1);
    for (int loop = 0; loop < count; loop++ ) {
        stringList.insert(row,"");
    }
    endInsertRows();
    return true;
}
bool StringListModel::removeRows(int row, int count, const QModelIndex &parent)
{
    beginRemoveRows(QModelIndex(), row, row+count-1);
    for (int loop = 0; loop < count; loop++) {
        stringList.removeAt(row);
    }
    endRemoveRows();
    return true;
}










0 0
原创粉丝点击