天天看点

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

1 模型/视图架构

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

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个属性:行号,列号和父项的模型索引

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

2.2 行和列

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

2.3 父项

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

2.4 项角色

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

QtCreator 模块/视图编程( 一) 模型类,自定义模型QStringListModel,QStandardItemModel,QFileSystemModel,QSqlQueryModel,
#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;      
}      

继续阅读