模型/视图编程
Qt中的模型/视图架构用来实现大量的数据存储、处理及显示。MVC(Model-View-Controller)包括了3个组件:模型(Model)是应用对象,用来表示数据;视图(View)是模型的用户界面,用来显示数据;控制(Controller)定义了用户界面对用户输入的反应方式。委托(Delegate)用于定制数据的渲染和编辑方式。
1.模型
所有的模型都基于QAbstractItemModel类,该类提供了十分灵活的接口来处理各种视图,这些视图可以将数据的表现形式为表格
(table)、列表
(list)、树
(tree)。
Qt提供了一些现成的模型来处理数据项:
QStringListModel
存储简单的QString项目列表;
QStandardItemModel
管理复杂的属性结构数据项,每一个数据项可以包含任意的数据;
QFileSystemModel
提供了本地文件系统中文件和目录信息;
QSqlQueryModel
、QSqlTableModel
和QSqlRelationTableModel
用来访问数据库。
标准模型还无法满足需要时,可子类化QAbstractItemModel
、QAbstractListModel
或QAbstractTableModel
来创建自定义的模型。
常见的3种模型为列表模型
、表格模型
、树模型
,如下图所示:
为确保数据的表示与数据的获取相分离,Qt引入了模型索引的概念,输入和委托均可通过模型索引来请求数据并显示。只有模型需要知道怎样获取数据,被模型管理的数据类型可以被广泛的定义。模型索引包含一个指针,指向创建他们的模型,使用多个模型时可避免混淆。模型索引QModelIndex类提供对一块数据的临时引用,用来修改或检索模型中的数据,获取一个数据项的模型索引必须指定模型的3个属性:行号、列号和父项的模型索引。如
:
QModelIndex index = model->index(row,column,parent);
也可通过模型指定的相关数据项对应的模型索引以及特定的角色来获取需要的类型数据,如
:
QVariant value = model->data(index,role);
常用的角色类型:
2.视图
Qt提供了QListView、QTableView视图、QTreeView视图分别实现列表、表格与树视图效果。QListView将数据项显示为一个列表;QTableView将模型中的数据显示在一个表格中;QTreeView将模型中的数据项显示在具有层次的列表中。QTableView和QTreeView在显示项目的时候同时还可以显示标头,通过QHeaderView类实现。自定义视图类是基于QAbstractItemView抽象基类,如实现条形图,饼状图等特殊显示方式。
视图类的选择行为
视图类的选择模式
选择模型更新方式
具体操作
StringListModel : public QAbstrctListModel
具体代码
testModel.pro
stringlistmodel.h
#ifndef STRINGLISTMODEL_H
#define STRINGLISTMODEL_H
#include <QAbstractListModel>
class StringListModel : public QAbstractListModel
{
Q_OBJECT
public:
StringListModel(const QStringList &strings, QObject *parent = 0):QAbstractListModel(parent), m_stringList(strings){}
//模型行数
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;
//项目属性
Qt::ItemFlags flags(const QModelIndex &index) const;
//编辑数据
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
//插入行 参数(插入的位置, 插入等待行数, 父项的模型索引)
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
//删除行
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
private:
QStringList m_stringList;
};
#endif // STRINGLISTMODEL_H
stringlistmodel.cpp
#include "stringlistmodel.h"
int StringListModel::rowCount(const QModelIndex &parent) const
{
return m_stringList.count();
}
QVariant StringListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return QVariant();
if (index.row() == m_stringList.size()) return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole)
return m_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);
}
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)
{
m_stringList.replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return true;
}
bool StringListModel::insertRows(int position, int rows, const QModelIndex &index)
{
//告知其他组件指定的行开始插入操作
beginInsertRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row)
m_stringList.insert(position, QString("来自星星的你"));
//告别其他组件完成操作
endInsertRows();
return true;
}
bool StringListModel::removeRows(int position, int rows, const QModelIndex &index)
{
//告别其他组件指定的行开始删除操作
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row)
{
m_stringList.removeAt(position);
}
//告别其他组件完成操作
endRemoveRows();
return true;
}
main.cpp
#include <QApplication>
#include "stringlistmodel.h"
#include <QListView>
#include <QTableView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QStringList list;
list << QString("太阳") << QString("地球") << QString("月亮") << QString("木星");
StringListModel model(list); //创建模型
model.insertRows(3, 2);
model.removeRows(5, 1);
QListView listView; //创建列表视图
listView.setModel(&model); //视图设置模型
listView.show(); //视图显示
QTableView tableView; //创建表格视图
tableView.setModel(&model); //视图设置模型
tableView.show(); //视图显示
return app.exec();
}
结语:
时间: 2020-08-13