一、概述
Qt提供了一种略微不同于MVC(Model-View-Controller)的架构,称之为MVD(Model-View-Delgate)架构。即Controller实际上应由用户自己组合实现,Qt未提供专门的类来处理,Qt提供了一系列的Delegate协调Model和View,实现渲染、数据编辑和转换,不直接参与界面布局,而是与View配合进行细节控制以及将Model数据转换为View可用的格式。Qt 已经提供了一系列的Model、View、Delegate类以实现Model/View/Delegate架构。MVD架构可以实现数据和展示层的分离,使用MVD架构能够带来非常大的性能提升和开发的灵活性。
二、其它Model
常规Model使用的例子参见之前的文章。
除了常规的数据模型,还有一些处理对象用Model方式来表示会带来很大的便利。
如一些固定格式的文件,可将文件设置为一个Model,依次读取每行值存入Model中,在后面的处理时会十分方便。
下面介绍一个图片读取的例子,可以看到图像处理时使用Model的灵活性。这里需要说明一下,如果需要达到好的效果,应该配合Delegate对图片的绘制进行控制,此处仅仅为了说明Model因此没有使用Delegate。
本例的运行效果如下:

本例读取一张图片,然后把它绘制出来。
图片读取到一个Model中,Model的data方法定义了根据图片灰度值返回不同的字符,然后声明一个QTableView,QTableView加载这个Model,图片就绘制出来了,因此这张图片每个点实际对应QTableView的一个单元格。
具体步骤如下:
1. 首先定义ImageModel
1)ImageModel代表了读取的图片数据,数据索引的行对应图片像素的x值、列对应图片像素的y值。
2)ImageModel类中重载rowCount、columnCount、data以及headerData。
3)通过data方法返回每个索引(QModelIndex)所对应的数据,因此我们根据图片中该索引处(点)的灰度值大小,判断决定data方法所返回的字符值。预先定义了6个字符,由于灰度为256级,因此设定每256/6级灰度对应一种的字符。
Imagemodel.h内容如下:
#ifndef IMAGEMODEL_H
#define IMAGEMODEL_H
#include <QAbstractTableModel>
#include <QImage>
class ImageModel : public QAbstractTableModel
{
Q_OBJECT
public:
ImageModel(QObject *parent = 0);
void setImage(const QImage &image);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
private:
QImage modelImage;
};
#endif // IMAGEMODEL_H
imagemodel.cpp内容如下:
#include "imagemodel.h"
ImageModel::ImageModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
void ImageModel::setImage(const QImage &image)
{
beginResetModel();
modelImage = image;
endResetModel();
}
int ImageModel::rowCount(const QModelIndex & /* parent */) const
{
return modelImage.height();
}
int ImageModel::columnCount(const QModelIndex & /* parent */) const
{
return modelImage.width();
}
QVariant ImageModel::data(const QModelIndex &index, int role) const
{
const char mark[6] = {' ','.','-','+','o','@'};
const int DIM = 256.0/sizeof(mark)+0.5;
if (!index.isValid() || role != Qt::DisplayRole)
return QVariant();
int grey = qGray(modelImage.pixel(index.column(), index.row()))/DIM;
return QString(mark[grey]);
}
QVariant ImageModel::headerData(int /* section */,
Qt::Orientation /* orientation */,
int role) const
{
if (role == Qt::SizeHintRole)
return QSize(1, 1);
return QVariant();
}
2. 其次显示ImageModel
ImageModel仅仅代表了数据,初始化一个QTableView,然后setModel就可以看到显示效果了。这里的qt.png是一张64X64的图片,图片太大加载的时间会比较长。
#include <QApplication>
#include <QTableView>
#include <QHeaderView>
#include "imagemodel.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(images);
QApplication app(argc, argv);
ImageModel *model = new ImageModel();
QTableView* view = new QTableView;
view->setShowGrid(false); //将该值设为true可以更清晰地看出行/列与图片像素的关系
view->horizontalHeader()->hide();
view->verticalHeader()->hide();
view->horizontalHeader()->setMinimumSectionSize(1);
view->verticalHeader()->setMinimumSectionSize(1);
view->setModel(model);
QImage image;
if (image.load(":/images/qt.png")) {
model->setImage(image);
view->resizeColumnsToContents();
view->resizeRowsToContents();
}
view->show();
return app.exec();
}
相关代码见: https://download.csdn.net/download/cnbizz/90466827?spm=1001.2014.3001.5503
&spm=1001.2101.3001.5002&articleId=146113395&d=1&t=3&u=d78bc79e974b490898dd93a683189d18)
6635

被折叠的 条评论
为什么被折叠?



