QT MVC 编程 MODEL/DELEGATE/VIEW(三)

一、概述

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值