一、前言

随着移动互联网的盛行,现在手机APP大行其道,每个人的手机没有十几个APP都不好意思说自己是现代人,各种聊天、购物、直播、小视频等APP,有个陌生人社交的APP叫探探,本人用过几次,当然不是去为了找对象,而是纯粹为了好玩研究下他的U设计和软件逻辑流程等,其中有个雷达控件,单击以后可以搜索附近的异性进行配对,这个雷达控件的效果蛮好的,于是手痒琢磨着用Qt来实现一个,毕竟自己写了150多个控件了,已经上瘾了,对各种效果都如鱼得水,看到各种效果都不自然的想到编码思路等。

这个控件的核心其实就是外围的那个扫描圈和发散的扫描线,中间变大变小恢复正常的圆形头像,外围的扫描圈采用锥形渐变颜色,通过透明度控制形成扫描效果,核心方法就是drawPie,至于扩散圈,需要识别到单击以后将扩散圈存入队列,因为可能会单击多次,产生多个扩散圈,至于中间头像的动态效果,采用三个QPropertyAnimation来实现,一个负责变大,一个负责变小,一个负责恢复正常,然后三个动画加入到QSequentialAnimationGroup动画序列中,按照顺序执行。

二、实现的功能

  • 1:可设置中间图像
  • 2:可设置图像的边框宽度+边框颜色,产生圆形图像效果
  • 3:可设置扫描线的最大半径
  • 4:可设置扫描线的边框宽度
  • 5:可设置扩散圈的线条宽度
  • 6:可设置扫描线的每次移动的步长
  • 7:可设置扩散圈的每次移动的步长
  • 8:可设置扫描线的颜色
  • 9:可设置扩散圈的颜色

三、效果图

四、头文件代码

#ifndef SCANTANTAN_H
#define SCANTANTAN_H /**
* 探探雷达控件 作者:东门吹雪(QQ:709102202) 整理:feiyangqingyun(QQ:517216493) 2019-10-01
* 1:可设置中间图像
* 2:可设置图像的边框宽度+边框颜色,产生圆形图像效果
* 3:可设置扫描线的最大半径
* 4:可设置扫描线的边框宽度
* 5:可设置扩散圈的线条宽度
* 6:可设置扫描线的每次移动的步长
* 7:可设置扩散圈的每次移动的步长
* 8:可设置扫描线的颜色
* 9:可设置扩散圈的颜色
*/ #include <QWidget> class QSequentialAnimationGroup; #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT ScanTanTan : public QWidget
#else
class ScanTanTan : public QWidget
#endif {
Q_OBJECT
Q_PROPERTY(QPixmap image READ getImage WRITE setImage)
Q_PROPERTY(int imageBorderWidth READ getImageBorderWidth WRITE setImageBorderWidth)
Q_PROPERTY(QColor imageBorderColor READ getImageBorderColor WRITE setImageBorderColor) Q_PROPERTY(int scanRadius READ getScanRadius WRITE setScanRadius)
Q_PROPERTY(int scanWidth READ getScanWidth WRITE setScanWidth)
Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth) Q_PROPERTY(int scanStep READ getScanStep WRITE setScanStep)
Q_PROPERTY(int ringStep READ getRingStep WRITE setRingStep) Q_PROPERTY(QColor scanColor READ getScanColor WRITE setScanColor)
Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor) public:
struct RingData {
int radius; //半径
float width; //画笔粗细
int alpha; //透明度
}; explicit ScanTanTan(QWidget *parent = 0); protected:
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
void drawScan(QPainter *painter);
void drawRing(QPainter *painter);
void drawImage(QPainter *painter); private slots:
void changeScan();
void changeRing();
void updateImage(const QVariant &value);
double twoPtDistance(const QPointF &pt1, const QPointF &pt2); private:
QPixmap image; //中间图片
int imageBorderWidth; //图片边框宽度
QColor imageBorderColor;//图片边框颜色 int scanRadius; //扫描线最大半径
int scanWidth; //扫描线边框宽度
int ringWidth; //扩散圈线条宽度 int scanStep; //扫描线每次移动的步长
int ringStep; //扩散圈每次移动的步长 QColor scanColor; //扫描线颜色
QColor ringColor; //扩散圈颜色 bool isPressed; //鼠标是否按下
int ringRadius; //扩散圈半径
int imageRadius; //图片半径
int scanDeg; //当前扫描线角度 //扩散圈集合,鼠标可能按下多次则产生多个扩散圈,用队列存起来
QList<RingData> rings;
//动画组合,用于中间图片的变大放小
QSequentialAnimationGroup *animationGroup; public:
QPixmap getImage() const;
int getImageBorderWidth() const;
QColor getImageBorderColor()const; int getScanRadius() const;
int getScanWidth() const;
int getRingWidth() const; int getScanStep() const;
int getRingStep() const; QColor getScanColor() const;
QColor getRingColor() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
//设置图片+图片边框宽度+图片边框颜色
void setImage(const QPixmap &image);
void setImageBorderWidth(int imageBorderWidth);
void setImageBorderColor(const QColor &imageBorderColor); //设置扫描线最大半径+扫描线边框宽度+扩散圈线条宽度
void setScanRadius(int scanRadius);
void setScanWidth(int scanWidth);
void setRingWidth(int ringWidth); //设置扫描线步长+扩散圈步长
void setScanStep(int scanStep);
void setRingStep(int ringStep); //设置扫描线颜色+扩散圈颜色
void setScanColor(const QColor &scanColor);
void setRingColor(const QColor &ringColor);
}; #endif // SCANTANTAN_H

五、核心代码

void ScanTanTan::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height); //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0); //绘制扫描线
drawScan(&painter);
//绘制扩散圈
drawRing(&painter);
//绘制中间图片
drawImage(&painter);
} void ScanTanTan::drawScan(QPainter *painter)
{
painter->save(); //锥形渐变颜色,通过透明度控制形成扫描效果
QConicalGradient conicalGradient(0, 0, scanDeg);
QColor color = scanColor;
color.setAlpha(50);
conicalGradient.setColorAt(0, color);
color.setAlpha(0);
conicalGradient.setColorAt(1, color); //设置画笔画刷
QPen pen;
pen.setWidth(scanWidth);
pen.setBrush(conicalGradient);
painter->setPen(pen);
painter->setBrush(conicalGradient); //绘制饼圆
QRect rect(-scanRadius, -scanRadius, scanRadius * 2, scanRadius * 2);
painter->drawPie(rect, scanDeg * 16, 360 * 16); painter->restore();
} void ScanTanTan::drawRing(QPainter *painter)
{
painter->save();
painter->setBrush(Qt::NoBrush); //绘制所有扩散圈,扩散圈其实就是个没有背景颜色的圆形
for (int i = 0; i < rings.count(); i++) {
RingData ring = rings.at(i);
int radius = ring.radius;
float width = ring.width;
int alpha = 255 - ring.alpha;
QColor color = ringColor;
color.setAlpha(alpha); QPen pen;
pen.setWidthF(width);
pen.setColor(color);
painter->setPen(pen);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
} painter->restore();
} void ScanTanTan::drawImage(QPainter *painter)
{
painter->save(); //设置圆形遮罩路径,产生圆形头像效果
QPainterPath path;
path.addEllipse(QPoint(0, 0), imageRadius, imageRadius);
painter->setClipPath(path); //绘制图片
QRect rect(-imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2);
painter->drawPixmap(rect, image); //绘制图片边缘圆形
QPen pen;
pen.setWidth(imageBorderWidth);
pen.setColor(imageBorderColor);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush); //以下两种方法二选一,其实绘制360度的圆弧=绘制无背景的圆形
//painter->drawArc(rect, 0, 360 * 16);
painter->drawEllipse(rect); painter->restore();
}

六、控件介绍

  1. 超过160个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.13的任何Qt版本,支持mingw、msvc、gcc等编译器,支持任意操作系统比如windows+linux+mac+嵌入式linux等,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
  4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
  5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
  6. 每个控件默认配色和demo对应的配色都非常精美。
  7. 超过130个可见控件,6个不可见控件。
  8. 部分控件提供多种样式风格选择,多种指示器样式选择。
  9. 所有控件自适应窗体拉伸变化。
  10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
  11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
  12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
  13. 所有控件最后生成一个动态库文件(dll或者so等),可以直接集成到qtcreator中拖曳设计使用。
  14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。
  15. 自定义控件插件开放动态库使用(永久免费),无任何后门和限制,请放心使用。
  16. 目前已提供26个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  17. 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  18. Qt入门书籍推荐霍亚飞的《Qt Creator快速入门》《Qt5编程入门》,Qt进阶书籍推荐官方的《C++ GUI Qt4编程》。
  19. 强烈推荐程序员自我修养和规划系列书《大话程序员》《程序员的成长课》《解忧程序员》,受益匪浅,受益终生!
  20. SDK地址:https://gitee.com/feiyangqingyun/QUCSDK

Qt编写自定义控件62-探探雷达的更多相关文章

  1. Qt编写自定义控件二动画按钮

    现在的web发展越来越快,很多流行的布局样式,都是从web开始的,写惯了Qt widgets 项目,很多时候想改进一下现有的人机交互,尤其是在现有的按钮上加一些动画的效果,例如鼠标移上去变大,移开还原 ...

  2. Qt编写自定义控件10-云台仪表盘

    前言 做过安防视频监控的同学都清楚,在视频监控系统软件上都可以看到一个云台控制区域,可以对球机进行下下左右等八个方位的运动控制,还可以进行复位,一般都是美工作图好,然后贴图的形式加入到软件中,好处是程 ...

  3. Qt编写自定义控件3-速度仪表盘

    前言 速度仪表盘,写作之初的本意是用来展示当前测试的网速用的,三色圆环+数码管显示当前速度,Qt自带了数码管控件QLCDNumber,直接集成即可,同时还带有动画功能,其实也可以用在汽车+工业领域等, ...

  4. Qt编写自定义控件插件开放动态库dll使用(永久免费)

    这套控件陆陆续续完善了四年多,目前共133个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本 ...

  5. Qt编写自定义控件11-设备防区按钮控件

    前言 在很多项目应用中,需要根据数据动态生成对象显示在地图上,比如地图标注,同时还需要可拖动对象到指定位置显示,能有多种状态指示,安防领域一般用来表示防区或者设备,可以直接显示防区号,有多种状态颜色指 ...

  6. Qt编写自定义控件9-导航按钮控件

    前言 导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CSS2 ...

  7. Qt编写自定义控件8-动画按钮组控件

    前言 动画按钮组控件可以用来当做各种漂亮的导航条用,既可以设置成顶部底部+左侧右侧,还自带精美的滑动效果,还可以设置悬停滑动等各种颜色,原创作者雨田哥(QQ:3246214072),驰骋Qt控件界多年 ...

  8. Qt编写自定义控件7-自定义可拖动多边形

    前言 自定义可拖动多边形控件,原创作者是赵彦博(QQ:408815041 zyb920@hotmail.com),创作之初主要是为了能够在视频区域内用户自定义可拖动的多个区域,即可用来作为警戒区域,也 ...

  9. Qt编写自定义控件6-指南针仪表盘

    前言 指南针仪表盘,主要用来指示东南西北四个方位,双向对称两个指针旋转,其实就是360度打转,功能属于简单型,可能指针的绘制稍微难一点,需要计算多个点构成多边形,本系列控件文章将会连续发100+篇,一 ...

随机推荐

  1. go语言-for循环

    一.for循环语法: for 循环变量初始化:循环条件:循环变量迭代{ 循环体 }案例: 打印10句hello 方式一 package main import "fmt" func ...

  2. 微信支付(APP支付)-服务端开发(二 )

    如果你已经可以微信支付成功,那么你已经成功90%,剩下的就是订单确认问题了. 接上一篇文章,今天我们来谈一谈,订单查询与确认: APP端支付成功之后,会再次向服务端发起请求,确认付款订单时候成功,同时 ...

  3. Codeforces Round #604 (Div. 2) A. Beautiful String

    链接: https://codeforces.com/contest/1265/problem/A 题意: A string is called beautiful if no two consecu ...

  4. LightOJ - 1102 - Problem Makes Problem(组合数)

    链接: https://vjudge.net/problem/LightOJ-1102 题意: As I am fond of making easier problems, I discovered ...

  5. Spark运行架构及作业提交流程

    1.yarn-cluster模式: (1)client客户端提交spark Application应用程序到yarn集群. (2)ResourceManager收到了请求后,在集群中选择一个NodeM ...

  6. Continuous Subarray Sum II

    Description Given an circular integer array (the next element of the last element is the first eleme ...

  7. go条件变量同步机制

    sync.Cond代表条件变量,需要配置锁才能有用 package main import ( "fmt" "runtime" "sync" ...

  8. Kubernetes 学习26 基于kubernetes的Paas概述

    一.概述 1.通过以往的学习应该可以了解到k8s 和以往提到的devops概念更容易落地了.比如我们说的CI,CD,CD a.CI(Continuous Integration):持续集成 b.CD( ...

  9. 汇编语言笔记 CALL和RET指令

    转载地址:http://www.cnblogs.com/dennisOne ☞模块化程序设计 模块化程序设计 汇编语言通过call和ret指令实现了模块化程序设计.可以实现多个相互联系.功能独立的子程 ...

  10. Poj 3233 Matrix Power Series(矩阵乘法)

    Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Description Given a n × n matrix A and ...