• 2416阅读
  • 3回复

Qt编写自定义控件62-探探雷达 [复制链接]

上一主题 下一主题
离线liudianwu
 

只看楼主 倒序阅读 楼主  发表于: 2019-10-07
一、前言
随着移动互联网的盛行,现在手机APP大行其道,每个人的手机没有十几个APP都不好意思说自己是现代人,各种聊天、购物、直播、小视频等APP,有个陌生人社交的APP叫探探,本人用过几次,当然不是去为了找对象,而是纯粹为了好玩研究下他的U设计和软件逻辑流程等,其中有个雷达控件,单击以后可以搜索附近的异性进行配对,这个雷达控件的效果蛮好的,于是手痒琢磨着用Qt来实现一个,毕竟自己写了150多个控件了,已经上瘾了,对各种效果都如鱼得水,看到各种效果都不自然的想到编码思路等。
这个控件的核心其实就是外围的那个扫描圈和发散的扫描线,中间变大变小恢复正常的圆形头像,外围的扫描圈采用锥形渐变颜色,通过透明度控制形成扫描效果,核心方法就是drawPie,至于扩散圈,需要识别到单击以后将扩散圈存入队列,因为可能会单击多次,产生多个扩散圈,至于中间头像的动态效果,采用三个QPropertyAnimation来实现,一个负责变大,一个负责变小,一个负责恢复正常,然后三个动画加入到QSequentialAnimationGroup动画序列中,按照顺序执行。

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

三、效果图


  
四、头文件代码
  1. #ifndef SCANTANTAN_H
  2. #define SCANTANTAN_H
  3. /**
  4. * 探探雷达控件 作者:东门吹雪(QQ:709102202) 整理:feiyangqingyun(QQ:517216493) 2019-10-01
  5. * 1:可设置中间图像
  6. * 2:可设置图像的边框宽度+边框颜色,产生圆形图像效果
  7. * 3:可设置扫描线的最大半径
  8. * 4:可设置扫描线的边框宽度
  9. * 5:可设置扩散圈的线条宽度
  10. * 6:可设置扫描线的每次移动的步长
  11. * 7:可设置扩散圈的每次移动的步长
  12. * 8:可设置扫描线的颜色
  13. * 9:可设置扩散圈的颜色
  14. */
  15. #include <QWidget>
  16. class QSequentialAnimationGroup;
  17. #ifdef quc
  18. #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
  19. #include <QtDesigner/QDesignerExportWidget>
  20. #else
  21. #include <QtUiPlugin/QDesignerExportWidget>
  22. #endif
  23. class QDESIGNER_WIDGET_EXPORT ScanTanTan : public QWidget
  24. #else
  25. class ScanTanTan : public QWidget
  26. #endif
  27. {
  28.     Q_OBJECT
  29.     Q_PROPERTY(QPixmap image READ getImage WRITE setImage)
  30.     Q_PROPERTY(int imageBorderWidth READ getImageBorderWidth WRITE setImageBorderWidth)
  31.     Q_PROPERTY(QColor imageBorderColor READ getImageBorderColor WRITE setImageBorderColor)
  32.     Q_PROPERTY(int scanRadius READ getScanRadius WRITE setScanRadius)
  33.     Q_PROPERTY(int scanWidth READ getScanWidth WRITE setScanWidth)
  34.     Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth)
  35.     Q_PROPERTY(int scanStep READ getScanStep WRITE setScanStep)
  36.     Q_PROPERTY(int ringStep READ getRingStep WRITE setRingStep)
  37.     Q_PROPERTY(QColor scanColor READ getScanColor WRITE setScanColor)
  38.     Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor)
  39. public:
  40.     struct RingData {
  41.         int radius;     //半径
  42.         float width;    //画笔粗细
  43.         int alpha;      //透明度
  44.     };
  45.     explicit ScanTanTan(QWidget *parent = 0);
  46. protected:
  47.     void mousePressEvent(QMouseEvent *);
  48.     void mouseReleaseEvent(QMouseEvent *);
  49.     void paintEvent(QPaintEvent *);
  50.     void drawScan(QPainter *painter);
  51.     void drawRing(QPainter *painter);
  52.     void drawImage(QPainter *painter);
  53. private slots:
  54.     void changeScan();
  55.     void changeRing();
  56.     void updateImage(const QVariant &value);
  57.     double twoPtDistance(const QPointF &pt1, const QPointF &pt2);
  58. private:
  59.     QPixmap image;          //中间图片
  60.     int imageBorderWidth;   //图片边框宽度
  61.     QColor imageBorderColor;//图片边框颜色
  62.     int scanRadius;         //扫描线最大半径
  63.     int scanWidth;          //扫描线边框宽度
  64.     int ringWidth;          //扩散圈线条宽度
  65.     int scanStep;           //扫描线每次移动的步长
  66.     int ringStep;           //扩散圈每次移动的步长
  67.     QColor scanColor;       //扫描线颜色
  68.     QColor ringColor;       //扩散圈颜色
  69.     bool isPressed;         //鼠标是否按下
  70.     int ringRadius;         //扩散圈半径
  71.     int imageRadius;        //图片半径
  72.     int scanDeg;            //当前扫描线角度
  73.     //扩散圈集合,鼠标可能按下多次则产生多个扩散圈,用队列存起来
  74.     QList<RingData> rings;
  75.     //动画组合,用于中间图片的变大放小
  76.     QSequentialAnimationGroup *animationGroup;
  77. public:
  78.     QPixmap getImage()          const;
  79.     int getImageBorderWidth()   const;
  80.     QColor getImageBorderColor()const;
  81.     int getScanRadius()         const;
  82.     int getScanWidth()          const;
  83.     int getRingWidth()          const;
  84.     int getScanStep()           const;
  85.     int getRingStep()           const;
  86.     QColor getScanColor()       const;
  87.     QColor getRingColor()       const;
  88.     QSize sizeHint()            const;
  89.     QSize minimumSizeHint()     const;
  90. public Q_SLOTS:
  91.     //设置图片+图片边框宽度+图片边框颜色
  92.     void setImage(const QPixmap &image);
  93.     void setImageBorderWidth(int imageBorderWidth);
  94.     void setImageBorderColor(const QColor &imageBorderColor);
  95.     //设置扫描线最大半径+扫描线边框宽度+扩散圈线条宽度
  96.     void setScanRadius(int scanRadius);
  97.     void setScanWidth(int scanWidth);
  98.     void setRingWidth(int ringWidth);
  99.     //设置扫描线步长+扩散圈步长
  100.     void setScanStep(int scanStep);
  101.     void setRingStep(int ringStep);
  102.     //设置扫描线颜色+扩散圈颜色
  103.     void setScanColor(const QColor &scanColor);
  104.     void setRingColor(const QColor &ringColor);
  105. };
  106. #endif // SCANTANTAN_H

五、核心代码
  1. void ScanTanTan::paintEvent(QPaintEvent *)
  2. {
  3.     int width = this->width();
  4.     int height = this->height();
  5.     int side = qMin(width, height);
  6.     //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
  7.     QPainter painter(this);
  8.     painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
  9.     painter.translate(width / 2, height / 2);
  10.     painter.scale(side / 200.0, side / 200.0);
  11.     //绘制扫描线
  12.     drawScan(&painter);
  13.     //绘制扩散圈
  14.     drawRing(&painter);
  15.     //绘制中间图片
  16.     drawImage(&painter);
  17. }
  18. void ScanTanTan::drawScan(QPainter *painter)
  19. {
  20.     painter->save();
  21.     //锥形渐变颜色,通过透明度控制形成扫描效果
  22.     QConicalGradient conicalGradient(0, 0, scanDeg);
  23.     QColor color = scanColor;
  24.     color.setAlpha(50);
  25.     conicalGradient.setColorAt(0, color);
  26.     color.setAlpha(0);
  27.     conicalGradient.setColorAt(1, color);
  28.     //设置画笔画刷
  29.     QPen pen;
  30.     pen.setWidth(scanWidth);
  31.     pen.setBrush(conicalGradient);
  32.     painter->setPen(pen);
  33.     painter->setBrush(conicalGradient);
  34.     //绘制饼圆
  35.     QRect rect(-scanRadius, -scanRadius, scanRadius * 2, scanRadius * 2);
  36.     painter->drawPie(rect, scanDeg * 16, 360 * 16);
  37.     painter->restore();
  38. }
  39. void ScanTanTan::drawRing(QPainter *painter)
  40. {
  41.     painter->save();
  42.     painter->setBrush(Qt::NoBrush);
  43.     //绘制所有扩散圈,扩散圈其实就是个没有背景颜色的圆形
  44.     for (int i = 0; i < rings.count(); i++) {
  45.         RingData ring = rings.at(i);
  46.         int radius = ring.radius;
  47.         float width = ring.width;
  48.         int alpha = 255 - ring.alpha;
  49.         QColor color = ringColor;
  50.         color.setAlpha(alpha);
  51.         QPen pen;
  52.         pen.setWidthF(width);
  53.         pen.setColor(color);
  54.         painter->setPen(pen);
  55.         painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
  56.     }
  57.     painter->restore();
  58. }
  59. void ScanTanTan::drawImage(QPainter *painter)
  60. {
  61.     painter->save();
  62.     //设置圆形遮罩路径,产生圆形头像效果
  63.     QPainterPath path;
  64.     path.addEllipse(QPoint(0, 0), imageRadius, imageRadius);
  65.     painter->setClipPath(path);
  66.     //绘制图片
  67.     QRect rect(-imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2);
  68.     painter->drawPixmap(rect, image);
  69.     //绘制图片边缘圆形
  70.     QPen pen;
  71.     pen.setWidth(imageBorderWidth);
  72.     pen.setColor(imageBorderColor);
  73.     painter->setPen(pen);
  74.     painter->setBrush(Qt::NoBrush);
  75.     //以下两种方法二选一,其实绘制360度的圆弧=绘制无背景的圆形
  76.     //painter->drawArc(rect, 0, 360 * 16);
  77.     painter->drawEllipse(rect);
  78.     painter->restore();
  79. }

六、控件介绍
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](https://gitee.com/feiyangqingyun/QUCSDK)
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线zqxwce007

只看该作者 1楼 发表于: 2019-10-08
大佬,效果图呢
离线mengkun

只看该作者 2楼 发表于: 2019-10-08
码云上的图片要登录才能看到……

我来补充一下效果图吧

离线liudianwu

只看该作者 3楼 发表于: 2019-10-08
回 zqxwce007 的帖子
zqxwce007:大佬,效果图呢 (2019-10-08 08:15) 

现在呢,再看下有没有。
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个