qt实现头像上传功能

想必大家都使用过qt的自定义头像功能吧,那么图1应该不会陌生,本片文章我就是要模拟一个这样的功能,虽然没有这么强大的效果,但是能够满足一定的需求。

图1 qq上传图片

首先在讲解功能之前,我先给出一片文章,QT实现的类似QQ的头像选择框,这篇文章也是讲解头像上传功能的,而我自己的代码是从这个demo中优化而来,不仅对代码进行了重构,而且处理了快速拖动时,边框消失的问题。使用事件和双缓冲来尽量减少重新绘制的几率。接下里我会一步一步进行讲解,怎么实现图片自定义截取功能。

一、概要

首选,我给出4个类,并给出他们的解释

1、PicturePreviewPanel:图标展示框,控件基类

2、BackgroundWidget:阴影窗口,是PicturePreviewPanel子类

3、CutShape:交互图形基类,实现了拖拽和放大缩小功能

4、CutRound:圆形剪贴,父类为CutShape,实现父类的paintInit接口重绘

5、CutRectangle:矩形剪贴,父类为CutShape,实现父类的paintInit接口重绘

二、详情

理解了上述5个类之后,接下来我分别讲解下类的头文件和重要的实现接口,其中自定义图形类也可以自己在扩充

头文件代码如下,有部分注释,代码应该不难理解,开发过程中只需要声明PicturePreviewPanel类,并调用期LoadPicture接口就可以加载图片,并进行图片剪切

View Code

上述头文件,如果觉得麻烦了也可以不具体细看接口,只要理解了标题1下边的5个类的作用就可以了。下边我分别说下交互图形类、背景色类和显示图片类(即控件基类)这三者直接的一些关系,具体如下:

1、CutShape剪贴图基类 实现了基本的交互功能,并绘制了部分图案,主要的绘制在子类实现,通过实现paintInit接口,该接口在剪切图街基类重新绘制时调用,代码如下:

 1 void CutShape::paintEvent(QPaintEvent * event)
 2 {
 3     QPainter paint;
 4     if (m_EnableRepaint && paintInit(event, &m_BufferPix))
 5     {
 6         m_EnableRepaint = false;
 7         qDebug() << "event->type()" << event->type();
 8         m_BufferPix = QPixmap(size());
 9         m_BufferPix.fill(Qt::transparent);
10 
11         paint.begin(&m_BufferPix);
12         QPen pen0;
13         pen0.setColor(QColor(54, 158, 254, 120));
14         pen0.setWidth(2);
15         paint.setPen(pen0);
16         paint.drawRect(border, border, width() - border * 2, width() - border * 2);
17 
18         QPen pen;
19         QVector<qreal> dashes;
20         qreal space = 3;
21         dashes << 5 << space << 5 << space;
22         pen.setDashPattern(dashes);
23         pen.setColor(Qt::white);
24 
25         paint.setPen(pen);
26         int x_pos = (int)width() / 3.0;
27         int y_pos = (int)height() / 3.0;
28         paint.drawLine(x_pos, border, x_pos, height() - 2 * border);
29         paint.drawLine(2 * x_pos, border, 2 * x_pos, height() - 2 * border);
30         paint.drawLine(border, y_pos, width() - 2 * border, y_pos);
31         paint.drawLine(border, 2 * y_pos, width() - 2 * border, 2 * y_pos);
32         paint.end();
33     }
34     paint.begin(this);
35     paint.drawPixmap(rect(), m_BufferPix);
36     paint.end();
37 }

上边是主要的绘制过程,关于剪切图形的交互功能,我给出具体的大姨妈,就不仔细讲解功能了,代码有些长,如下:

View Code

2、BackgroundWidget背景色窗口,该窗口作为剪切窗口的父类窗口,但是没有布局,目的就是可以让剪切窗口自由的移动,并保持在背景色窗口之上,当背景色窗口重新绘制的时候,只绘制除剪切窗口以外的部分。这样就实现了剪切窗口是透明的但是其余部分都是半透明的,代码如下:

 1 void BackgroundWidget::paintEvent(QPaintEvent *)
 2 {
 3     QPainterPath painterPath;
 4     QPainterPath p;
 5     p.addRect(x(), y(), rect().width(), rect().height());
 6     if (m_CutShape)
 7     {
 8         painterPath.addPath(m_CutShape->CutRegion().translated(m_CutShape->pos()));
 9     }
10     QPainterPath drawPath = p.subtracted(painterPath);
11 
12     QPainter paint(this);
13     paint.setOpacity(0.5);
14     paint.fillPath(drawPath, QBrush(Qt::black));
15 }

3、PicturePreviewPanel图片上传控件基类,当图片加载后,需要重置背景色窗口的大小,以便覆盖到图片之上,代码如下:

 1 bool PicturePreviewPanel::eventFilter(QObject * watched, QEvent * event)
 2 {
 3     if (watched == m_PictureContainer)
 4     {
 5         if (event->type() == QEvent::Resize)
 6         {
 7             LoadPicture_p();
 8             if (m_BgWidget)
 9             {
10                 m_BgWidget->resize(m_PictureContainer->size());
11             }
12         }
13     }
14     return QWidget::eventFilter(watched, event);
15 }

之所以需要重新加载图片是,放置图片因为拖拉而失真,图片的加载的加载代码如下:

 1 void PicturePreviewPanel::LoadPicture_p()
 2 {
 3     QPixmap picture;
 4     picture.load(m_PicturePath);
 5     if (!picture.isNull())
 6     {
 7         picture = picture.scaled(m_PictureContainer->width(), m_PictureContainer->height());
 8         m_PictureContainer->setPixmap(picture);
 9         m_BgWidget->PictureLoadFinished();
10     }
11 }

好了,有了上边的代码之后,这个图片上传空间的基本交互功能就完成了,点击保存截取图片,可以使用剪贴图基类的CutRegion方法获取剪贴的路径,并保存成指定图片格式。效果如图2所示

图2 效果展示

转载:https://www.cnblogs.com/swarmbees/p/5688885.html

作者:朝十晚八

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值