Qt 用 MVD(model view delegate) 模式 把图片变为灰度像素点 [官方Example]

前言:

今天看到一个好玩的 qt 官方的 demo

可以把图片 变为 一个个灰度的像素点

先来看一下

这个是 qt 的图片
在这里插入图片描述
这个是我加载的 我的头像
在这里插入图片描述

在这里插入图片描述

不过 看 这个 demo
需要了解 Qt 的 MVD 模式

model view delegate

如果你没有听说过 mvd mvc 应该听说过吧 model view control

qt 这里把control 换成了 delegate 委托 其实差不多

我这里做个简单的介绍 大体了解熟悉 m v d

mvd(model - view - delegate)

很早之前 list 或者 view 在加载数据 进行显示时 如果数据量比较大 就会比较卡
比如 5w 条数据,他的内部的实现逻辑是 把这些数据全部加载到内存
但是他一页就显示 100行数据
后面为了解决这个问题 就改为 既用既加载 用100行数据 那么我就只加载100行
翻页或者下拉滑动条 我在加载 下面的数据到内存
又引来了个新问题 如果我快速的翻页 或者 拖拉滑动条 那么也会出现 卡顿 白屏等
数据加载跟不上的现象

让一个类 来处理数据的加载和显示 交互 难免太庞大

这个 MVD 就出来了

下面挂几个结构图 说一下 MVD

在这里插入图片描述
在这里插入图片描述

Data 就是 数据 比如 从 文件中加载,数据库中加载 ,网口 ,串口数据 等

Model 类 负责加载数据

View类 负责显示数据,具体显示什么样的数据,全都有 delegate 来决定

Delegate 负责 把 model 的数据 做一些处理 给 view 显示
比如 model 的数据是 用户消费信心
delegate 可以 根据不同的形式 paint 成 柱状图 饼图 条形图 给到 view 显示
view 用户操作界面 修改了一些 信息 还是通过 delegate 去修改 model

这里就做一些简单的 介绍
具体的 MVD 还是要去看 MVD 的文章

系统提供模式 这个模式 只能完成一些基本的简单的功能
如果想完成一些其他的 我们要重写 model 和 delegate

这个 demo 也就是这样的 操作 咱们来看一下

Pixelator Example

介绍:
默认情况下,QTreeView、QTableView和QListView使用一个标准的项目委托来显示和编辑一组公共数据类型,这对于许多应用程序来说已经足够了。但是,应用程序可能需要以特定的方式表示数据项,或者为呈现更专门的数据类型提供支持,这通常需要使用自定义委托

在本例中,我们将展示如何使用自定义委托来修改标准视图的外观。为此,我们实现了以下组件:
一种模型,它将图像中的每个像素表示为一个数据项,其中每个数据项包含对应像素的亮度值。
自定义委托,它使用模型提供的信息将每个像素表示为白色背景上的黑色圆圈,圆圈的半径对应于像素的黑暗。

此示例对于希望实现自己的表模型或自定义委托的开发人员可能很有用.

还是先看一下 类的结构
在这里插入图片描述

一个 自定义的 model imagemodel
一个 自定义的 delegate pixeldelegate
一个 mainwindow 主界面
一个 main 函数

还有 一个资源文件 qt.png 64* 64 像素的

在这里插入图片描述

在这里插入图片描述

ok 咱们来看 main 函数

main

在这里插入图片描述

初始化 资源

实例化 mainwindow

打开了一个图片

MainWindow

在这里插入图片描述

这个 Example 有个 打印图片的 功能 咱们这里就不看了 只看 MVD 的模式 把灰度图显示出来

类结构也很简单

ImageModel 等会看

看下 openImage

在这里插入图片描述

这个函数也没啥 就是加载一个 本地的图片
然后 更新一下 view

mainwindow 我们只需要看这一点就够了

在这里插入图片描述

一个 tableView

setShowGrid 显示不显示网格 效果如下

这是 不显示 网格
在这里插入图片描述

这是显示网格
在这里插入图片描述

可以查一下 就是 64x64 行列 因为这个图片 就是 64*64像素的 每个格子 一个像素点

view->setModel(model);
PixelDelegate *delegate = new PixelDelegate(this);
view->setItemDelegate(delegate);

给 view 设置了 model 是我们的 ImageModel
给 view 设置了委托delegate 是 我们的PiexlDelegate

所以我们主要看 这两个类就行了

ImageModel

在这里插入图片描述
由于我们只需要一个简单的只读表模型,所以我们只需要实现一些函数来指示图像的维数并向其他组件提供数据。

在这里插入图片描述

这个函数 在上面说的 加载 image 有调用这个接口

在这里插入图片描述
这个函数返回就是 行和列 就是返回的 64*64

由于图像是一个简单的二维结构,所以这些函数的父参数是未使用的。它们都简单地从底层图像对象返回相关大小。
data()函数返回与给定模型索引对应的项的数据,其格式适合于特定的角色

在这里插入图片描述:这个函数 就是数据函数了 把 图片转为灰度显示的函数了

在这个实现中,我们只检查模型索引是否有效,并且请求的角色是DisplayRole。如果是,则返回图像中相关像素的灰度值;否则,将返回空模型索引。
这个模型可以和QTableView一起显示图像中像素的整数值。但是,我们将实现一个自定义委托来以更艺术的方式显示此信息

拆开来看
modelImage.pixle(index.column(),indelx.row())

在这里插入图片描述

返回给定像素的颜色 (传入的是像素点位置)
在这里插入图片描述
这个就是 返回的灰度值 传入 rgb

在这里插入图片描述

我们返回(1,1)作为标题项的大小提示。如果我们不这样做,标题将默认为更大的尺寸,从而阻止我们显示非常小的项目(可以使用像素大小组合框来指定)。

ok 到这这里类就结束了

这个类的作用就是数据 数据就是 一张图片每个像素点的 灰度值
一共 64*64个像素点

那么 data 函数就执行 64*64次

那么灰度值只是一个int 数字啊
具体怎么显示出来的 要看 delegate 是怎么实现的了

PixelDelegate

在这里插入图片描述

这个类只提供了委托的基本特性,我们子类化QAbstractItemDelegate而不是QItemDelegate。
我们只需要在这个类中重新实现paint()和sizeHint()。
但是,我们还提供了一个特定于委托的setPixelSize()函数,这样我们就可以通过信号和插槽机制来更改委托的行为。

这个 setPixelSize()函数 就是 在这里插入图片描述

修改这个通过信号槽 改变 私有变量 pixelSize

在这里插入图片描述

默认是 12px

在这里插入图片描述
这里说一下 参数 QmodelIndex &indelx
view和delegate都可以使用QModelIndex,但是view只能使用QModelIndex进行读取,delegate只能修改。 所以 要获取 model 的数据 都是 通过 这个接口 modelIndex .model.data

每个item 都是由委托的paint()函数呈现的。
视图使用现成的QPainter对象调用这个函数,委托应该使用它来正确绘制项目的样式信息,以及模型中项目的索引:

这里就是 我们看到的每一个像素点 就是在这个函数里 paint 绘制出来的 根据model 里面的灰度值

在这里插入图片描述

咱们 一句一句看一下 这个函数

在这里插入图片描述
在这里插入图片描述
如果 像素点是选中状态 那么会填充 这个 矩形 显示蓝色

在这里插入图片描述

首先,通过使用样式选项的rect属性的最小维度来确定圆的最大可能半径。
利用所提供的模型索引 ,我们获得了图像中相关像素的亮度值。圆的半径是通过调整亮度以适应项目并从最大可能的半径中减去它来计算的。

这个地方就是求半径的 看不懂也没关系 这就是它的一种计算方式

写到这里刚才停电了 我以为没有了 吓我一跳 写了一个小时啊
还好有保存

在这里插入图片描述
这里就 保存画笔的信息
开启抗锯齿模式

还是 根据 有没有选中 像素点 画不同的颜色
上面是填充的 外部矩形框的颜色
这个是 里面 圆形的颜色 选中以后变为 白色
下面一句就是根据 半径画一个圆形

在这里插入图片描述

有的圆大 有的圆小 都是由 半径决定的 半径又是有 model 里面的 图像的灰度值决定的

结束

ok 这个文章就结束了 他这个 Example 就是用了自定义 model 和 delegate 来完成的
要理解的比较好 还是要 多看一下 MVD 找一些MVD 的资料看一下

发布了194 篇原创文章 · 获赞 443 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/weixin_42837024/article/details/105387167