如题,如何使用Qt抠一个圆形头像出来?
先来看效果:

首先加载一张图片,显示一个透明圆形,圆形外半透明,滚动鼠标滚轮,圆形区域变大变小。
鼠标按下可以拖动图片移动,来选定要截取的图片位置,按下”剪切并保存“按钮后,将会截取圆形区域下的图片,得到一张圆形图片。比如:

来看一下运行效果:

实现原理如下:
这个窗口使用的是QGraphicsView,其中图片是继承自QGraphicsPixmapItemcustompixmap,这里重新实现了它的itemChange方法,以限制图片的移动范围:

QVariant custompixmap::itemChange(GraphicsItemChange change, const QVariant &value)
{if (change == ItemPositionChange  &&  scene()) // 控件发生移动{QPointF newPos = value.toPointF(); //即将移动的位置//限制的区域QRectF rect(-scene()->width() / 3, -scene()->width() / 3, (scene()->width() / 3) * 2, (scene()->width() / 3) * 2);SHOW(rect)if (!rect.contains(newPos)) // 是否在区域内{newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));return newPos;}}return QGraphicsItem::itemChange(change, value);
}

其中需要注意的是限制的区域的设定,比如这里的

QRectF rect(-scene()->width() / 3, -scene()->width() / 3, (scene()->width() / 3) * 2, (scene()->width() / 3) * 2);

这里scene的宽度为220,输出rect看一下:

QRectF(-73.3333,-73.3333 146.667x146.667)

那这个矩形的范围大概也就是这样:

也就是图片的左上角只能在这个矩形区域内活动,也就限制了图片移动的范围。
再来看圆形区域的绘制:
这里定义一个CustomView继承自QGraphicsView,重新实现它的paintEventwheelEvent方法:

int radius = 150;//半径
void CustomView::paintEvent(QPaintEvent *e)
{//https://www.it610.com/article/3860174.htm//先调用QGraphicsView::paintEvent(e);再画自己的QGraphicsView::paintEvent(e);//https://www.codenong.com/cs106784396/QPainter painter(this->viewport());QPainterPath path1;//构建圆形路径mPoint.setX((width() / 2) - radius / 2);mPoint.setY((height() / 2) - radius / 2);path1.addEllipse(mPoint.x(), mPoint.y(), radius, radius);SHOW(radius)//设置颜色为半透明QColor color(192, 192, 192, 150);//填充除去圆形的范围painter.setBrush(QBrush(color));QPainterPath path;//整个view的路径path.addRect(rect());//path减去圆形的范围path -= path1;painter.setClipPath(path);//画矩形,注意,这里把圆形范围剔除了painter.drawRect(rect());
}void CustomView::wheelEvent(QWheelEvent *event)
{QGraphicsView::wheelEvent(event);//限制圆形半径范围为[150,180]if(event->delta() > 0 && (radius - 10) >= 150){// 当滚轮远离使用者时radius -= 10;}else if (event->delta() < 0 && (radius + 10) <= 180){// 当滚轮向使用者方向旋转时radius += 10;}//https://www.codenong.com/cs106784396/this->viewport()->update();
}

paintEvent方法中填充一个半透明区域,注意要通过setClipPath减去一个圆形区域。在wheelEvent方法中根据滚轮,改变半径大小,并通过this->viewport()->update();刷新界面,重新绘制减去圆形区域的半透明区域,从而达到缩放圆形的效果。
当按下”剪切并保存“按钮后,根据当前圆形区域所在点的坐标及半径,并通过grab方法截取当前窗体这块区域:

void CustomView::grabPicture()
{SHOW(mPoint)//按照圆形所在矩形范围,截取当前截图QPixmap pixmap = grab(QRect(mPoint.x(), mPoint.y(), radius, radius));//截完后,扣圆形图片pixmap = PixmapToRound(pixmap, radius);//保存图片pixmap.save("here.png");
}


可以发现,这时截取的图片还不是圆形:
这里参考网上的方法,根据传入圆形区域的半径,抠取一个圆形图片:

//网上的方法,扣一个圆形图片出来
QPixmap PixmapToRound(const QPixmap &src, int radius)
{if (src.isNull()) {return QPixmap();}//构建一个透明的图片QPixmap pixmap(radius,radius);pixmap.fill(Qt::transparent);//在透明的图片上画QPainter painter(&pixmap);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);QPainterPath path;//画的范围为一个圆形path.addEllipse(0, 0, radius, radius);painter.setClipPath(path);//画图片painter.drawPixmap(0, 0, radius, radius, src);//返回这个图片return pixmap;
}

抠完后便得到了一个周围透明,形状为圆形的图片,保存即可!
所以,总结下来,前面做的工作都是根据用户鼠标的拖动及滚动确定要截取的图片大小及位置,之后通过截图截出一个小范围的图片,再根据圆形区域半径,抠一个圆形图片出来。嗯,就是酱~
正文结束。
下面介绍一种好用的调试方法:
我们可以新建一个common.h文件,里面定义一个调试用的宏:

#ifndef COMMON_H
#define COMMON_H#ifdef DEBUG#include <QDebug>
#endif#ifdef DEBUG
#define SHOW(x) qDebug() << #x << " : " << (x);
#else
#define SHOW(x)
#endif#endif // COMMON_H

在Qt的pro文件中,配置在debug模式下,定义一个DEBUG宏:

CONFIG(debug, debug|release) {DEFINES += DEBUG
}

这样,在需要输出某个变量值的时候,只需要引入common.h头文件,在需要打印变量时使用SHOW即可,比如:

#include "common.h"
int a = 1;
SHOW(a)

这样做的一个好处是,输出只在debug模式下才有,release模式下不会产生输出,并且不会额外增大源文件。
完~

最后来抠一个小姐姐的头像:

项目地址:https://gitee.com/gao-yuelong/qtdemo/tree/master/cutpicture
欢迎下载试玩!

如何用Qt抠一个圆形头像出来相关推荐

  1. 新手如何用QT做一个“动漫宠物“?进来学!!!!

    好久不见,又是这样的深夜,也算是忙里偷闲,分享下我前一段时间写的QT小玩具吧 交流群 1.效果展示 2.灵感 3.思路 4.代码部分 源码 交流群 698742127 想学习的小伙伴可以加一下,可以一 ...

  2. 如何用Qt设计一个多文档文本编辑器

    目录 前言 一.设计目标 二.效果展示 三.设计过程 1.设计思路 1.1文件的打开和新建 1.2设置字体和字号 1.3设置字型和颜色 1.4设置文字对齐撤销等 2.核心代码 总结 前言 学习了有关Q ...

  3. 使用css实现一个圆形头像框效果

    本文转载,记录下来方便以后查找 原文链接:https://www.php.cn/css-tutorial-406575.html 方法一 直接设置img为圆形,这种情况下如果图片不是正方形,图片会被拉 ...

  4. 如何用Matlab做一个3D头像

    https://mp.weixin.qq.com/s?__biz=MzU2MDc5Njg4NQ==&mid=2247483666&idx=1&sn=d96b21161da31f ...

  5. android 清空canvas部分内容_Android自定义View实现圆形头像效果

    在我们的APP中通常会遇到,展示圆形头像的需求,一般通过Glide就能实现,但是让我们做一个圆形头像,如果让我们自定义实现这种效果,该怎样做呢? 好,接下来本文通过三种方式来实现这种效果! 注意:这是 ...

  6. Qt实现一个简单的编译器(软件生成器)

    Qt实现一个简单的编译器(软件生成器) 本文章只记录如何用Qt实现一个简单编译器,即点击本软件中的按钮便可在另一目录中生成一个新的软件(与本软件不冲突). 文章目录 Qt实现一个简单的编译器(软件生成 ...

  7. Qt制作一个相册浏览工具

    如何用Qt制作一个相册浏览的小程序? 程序开发思路如下: 1.支持多张相片浏览,可翻页浏览,相片可从本地导入; 2.相片要有放大和缩小的功能; 3.相片可自动浏览,时间间隔可自定义. 主要的代码如下: ...

  8. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  9. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习...

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

最新文章

  1. SyntaxError: Non-ASCII character ‘\xe5‘ in file(xxlrt_1.py) on line 7, but no encoding declared;
  2. Jmeter使用jp@gc-stepping thread group做性能测试
  3. Vue+Openlayers实现加载天地图WMTS服务显示
  4. sql2016是否支持linux,微软 SQL Server 支持 Linux 了,2017年 中将正式推出
  5. ImportError: No module named 'pip._vendor.retrying'
  6. OpenGL 坐标变换
  7. 利用ASP .NET Core的静态文件原理实现远程访问Nlog日志内容及解决遇到的坑
  8. 前端学习(1752):前端调试值之网络请求的监控
  9. 工时单位天与人天的区别?
  10. vue可编辑div_vue2 如何实现div contenteditable=“true”(类似于v-model)的效果
  11. java基础:8.1 异常
  12. memcache的安装和使用
  13. vue-router自动判断左右翻页转场动画
  14. 《JavaScript高级程序设计(第3版)》.Nicholas.C.Zakas.扫描版.pdf
  15. 中英文国家名及手机号码前缀
  16. 为什么边缘概率密度是联合概率密度的积分_5.27005柏林联合VS美因茨
  17. 联众打码平台接口调用(初版)
  18. bootdo框架介绍使用
  19. java itex 打印pdf_Java使用iTextPDF生成PDF文件的实现方法
  20. List1_Excise

热门文章

  1. Servlet技术,response 生成图片验证码
  2. java webrtc降噪_android音频降噪webrtc
  3. 高德地图之周边信息查询
  4. SockJS简单介绍
  5. 从0开始学爬虫7之BeautifulSoup模块的简单介绍
  6. fitbit同步不了怎么解决_Fitbit 智能设备没有与安卓设备的 Fitbit 应用程序同步怎么办?...
  7. 超全文化艺术海外PPT模板素材网站整理
  8. USES_CONVERSION宏定义
  9. 13.深度学习之RNN进阶-1
  10. wifi测试软件推荐,推荐4个专业又实用的WiFi检测工具,了解一下