Qt纯代码绘制一个等候提示Ui控件

打印 上一主题 下一主题

主题 788|帖子 788|积分 2364

         等候样式控件是我们在做UI时出场率还挺高的控件之一,通常情况下有如下的几种实现方式:1、自界说绘图,然后重写paintEvent函数,在paintEvent中绘制等候图标,通过QTimer更新绘制达到转圈圈的结果。2、 获取一张gif的资源图,然后利用QMovie 在一个QLabel 控件上加载显示gif的waiting等候动态。
        本示例接纳自界说绘图,然后利用Qt动画,达到转圈圈的结果,给大家一个悦目的样式示例。你可以根据须要举行修改和扩展,实现你想要的程序启动等候提示栏结果。
想看利用QMovie实现的请移步:https://blog.csdn.net/u012959478/article/details/140441021
一、简述

         Qt纯代码绘制一个等候提示Ui控件。自界说绘图,然后重写paintEvent函数,在paintEvent中绘制等候图标,通过QTimer更新绘制达到转圈圈的结果。
二、 计划思绪   


  • 创建一个QWidget派生的自界说控件,用于显示等候提示。
  • 在自界说控件中,绘制一个圆形的等候图标。
  • 通过重写paintEvent函数,在paintEvent中绘制等候图标。
  • 利用定时器QTimer并实现一个槽函数来更新图标。
  • 在槽函数中调用update函数,触发重绘变乱,更新控件的显示。
三、结果 


四、焦点代码  

1、头文件

  1. #pragma once
  2. #include <QWidget>
  3. #include <QTimer>
  4. #include <QColor>
  5. class WaitingSpinnerWidget : public QWidget {
  6.     Q_OBJECT
  7. public:
  8.     WaitingSpinnerWidget(QWidget *parent = 0,
  9.                          bool centerOnParent = true,
  10.                          bool disableParentWhenSpinning = true);
  11.     WaitingSpinnerWidget(Qt::WindowModality modality,
  12.                          QWidget *parent = 0,
  13.                          bool centerOnParent = true,
  14.                          bool disableParentWhenSpinning = true);
  15. public slots:
  16.     void start();
  17.     void stop();
  18. public:
  19.     void setColor(QColor color);
  20.     void setRoundness(qreal roundness);//圆角
  21.     void setMinimumTrailOpacity(qreal minimumTrailOpacity);//最小轨迹不透明度
  22.     void setTrailFadePercentage(qreal trail);//轨迹褪色百分比
  23.     void setRevolutionsPerSecond(qreal revolutionsPerSecond);//每秒钟转数
  24.     void setNumberOfLines(int lines);//线条数量
  25.     void setLineLength(int length);//线条长度
  26.     void setLineWidth(int width);//线条宽度
  27.     void setInnerRadius(int radius);//内圆半径
  28.     QColor color();
  29.     qreal roundness();
  30.     qreal minimumTrailOpacity();
  31.     qreal trailFadePercentage();
  32.     qreal revolutionsPersSecond();
  33.     int numberOfLines();
  34.     int lineLength();
  35.     int lineWidth();
  36.     int innerRadius();
  37.     bool isSpinning() const;
  38. private slots:
  39.     void rotate();
  40. protected:
  41.     void paintEvent(QPaintEvent *paintEvent);
  42. private:
  43.     static int lineCountDistanceFromPrimary(int current, int primary,
  44.                                             int totalNrOfLines);
  45.     static QColor currentLineColor(int distance, int totalNrOfLines,
  46.                                    qreal trailFadePerc, qreal minOpacity,
  47.                                    QColor color);
  48.     void initialize();
  49.     void updateSize();
  50.     void updateTimer();
  51.     void updatePosition();
  52. private:
  53.     QColor  _color;
  54.     qreal   _roundness; // 0..100
  55.     qreal   _minimumTrailOpacity;
  56.     qreal   _trailFadePercentage;
  57.     qreal   _revolutionsPerSecond;
  58.     int     _numberOfLines;
  59.     int     _lineLength;
  60.     int     _lineWidth;
  61.     int     _innerRadius;
  62. private:
  63.     WaitingSpinnerWidget(const WaitingSpinnerWidget&);
  64.     WaitingSpinnerWidget& operator=(const WaitingSpinnerWidget&);
  65.     QTimer *_timer;
  66.     bool    _centerOnParent;
  67.     bool    _disableParentWhenSpinning;
  68.     int     _currentCounter;
  69.     bool    _isSpinning;
  70. };
复制代码
2、实当代码

  1. #include "waitingspinnerwidget.h"
  2. #include <cmath>
  3. #include <algorithm>
  4. #include <QPainter>
  5. #include <QTimer>
  6. WaitingSpinnerWidget::WaitingSpinnerWidget(QWidget *parent,
  7.                                            bool centerOnParent,
  8.                                            bool disableParentWhenSpinning)
  9.     : QWidget(parent),
  10.       _centerOnParent(centerOnParent),
  11.       _disableParentWhenSpinning(disableParentWhenSpinning) {
  12.     initialize();
  13. }
  14. WaitingSpinnerWidget::WaitingSpinnerWidget(Qt::WindowModality modality,
  15.                                            QWidget *parent,
  16.                                            bool centerOnParent,
  17.                                            bool disableParentWhenSpinning)
  18.     : QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint),
  19.       _centerOnParent(centerOnParent),
  20.       _disableParentWhenSpinning(disableParentWhenSpinning){
  21.     initialize();
  22.     // We need to set the window modality AFTER we've hidden the
  23.     // widget for the first time since changing this property while
  24.     // the widget is visible has no effect.
  25.     setWindowModality(modality);
  26.     setAttribute(Qt::WA_TranslucentBackground);
  27. }
  28. void WaitingSpinnerWidget::initialize() {
  29.     _color = Qt::black;
  30.     _roundness = 100.0;
  31.     _minimumTrailOpacity = 3.14159265358979323846;
  32.     _trailFadePercentage = 80.0;
  33.     _revolutionsPerSecond = 1.57079632679489661923;
  34.     _numberOfLines = 20;
  35.     _lineLength = 10;
  36.     _lineWidth = 2;
  37.     _innerRadius = 10;
  38.     _currentCounter = 0;
  39.     _isSpinning = false;
  40.     _timer = new QTimer(this);
  41.     connect(_timer, SIGNAL(timeout()), this, SLOT(rotate()));
  42.     updateSize();
  43.     updateTimer();
  44.     hide();
  45. }
  46. void WaitingSpinnerWidget::paintEvent(QPaintEvent *) {
  47.     updatePosition();
  48.     QPainter painter(this);
  49.     painter.fillRect(this->rect(), Qt::transparent);
  50.     painter.setRenderHint(QPainter::Antialiasing, true);
  51.     if (_currentCounter >= _numberOfLines) {
  52.         _currentCounter = 0;
  53.     }
  54.     painter.setPen(Qt::NoPen);
  55.     for (int i = 0; i < _numberOfLines; ++i) {
  56.         painter.save();
  57.         painter.translate(_innerRadius + _lineLength,
  58.                           _innerRadius + _lineLength);
  59.         qreal rotateAngle =
  60.                 static_cast<qreal>(360 * i) / static_cast<qreal>(_numberOfLines);
  61.         painter.rotate(rotateAngle);
  62.         painter.translate(_innerRadius, 0);
  63.         int distance =
  64.                 lineCountDistanceFromPrimary(i, _currentCounter, _numberOfLines);
  65.         QColor color =
  66.                 currentLineColor(distance, _numberOfLines, _trailFadePercentage,
  67.                                  _minimumTrailOpacity, _color);
  68.         painter.setBrush(color);
  69.         // TODO improve the way rounded rect is painted
  70.         painter.drawRoundedRect(
  71.                     QRect(0, -_lineWidth / 2, _lineLength, _lineWidth), _roundness,
  72.                     _roundness, Qt::RelativeSize);
  73.         painter.restore();
  74.     }
  75. }
  76. void WaitingSpinnerWidget::start() {
  77.     updatePosition();
  78.     _isSpinning = true;
  79.     show();
  80.     if(parentWidget() && _disableParentWhenSpinning) {
  81.         parentWidget()->setEnabled(false);
  82.     }
  83.     if (!_timer->isActive()) {
  84.         _timer->start();
  85.         _currentCounter = 0;
  86.     }
  87. }
  88. void WaitingSpinnerWidget::stop() {
  89.     _isSpinning = false;
  90.     hide();
  91.     if(parentWidget() && _disableParentWhenSpinning) {
  92.         parentWidget()->setEnabled(true);
  93.     }
  94.     if (_timer->isActive()) {
  95.         _timer->stop();
  96.         _currentCounter = 0;
  97.     }
  98. }
  99. void WaitingSpinnerWidget::setNumberOfLines(int lines) {
  100.     _numberOfLines = lines;
  101.     _currentCounter = 0;
  102.     updateTimer();
  103. }
  104. void WaitingSpinnerWidget::setLineLength(int length) {
  105.     _lineLength = length;
  106.     updateSize();
  107. }
  108. void WaitingSpinnerWidget::setLineWidth(int width) {
  109.     _lineWidth = width;
  110.     updateSize();
  111. }
  112. void WaitingSpinnerWidget::setInnerRadius(int radius) {
  113.     _innerRadius = radius;
  114.     updateSize();
  115. }
  116. QColor WaitingSpinnerWidget::color() {
  117.     return _color;
  118. }
  119. qreal WaitingSpinnerWidget::roundness() {
  120.     return _roundness;
  121. }
  122. qreal WaitingSpinnerWidget::minimumTrailOpacity() {
  123.     return _minimumTrailOpacity;
  124. }
  125. qreal WaitingSpinnerWidget::trailFadePercentage() {
  126.     return _trailFadePercentage;
  127. }
  128. qreal WaitingSpinnerWidget::revolutionsPersSecond() {
  129.     return _revolutionsPerSecond;
  130. }
  131. int WaitingSpinnerWidget::numberOfLines() {
  132.     return _numberOfLines;
  133. }
  134. int WaitingSpinnerWidget::lineLength() {
  135.     return _lineLength;
  136. }
  137. int WaitingSpinnerWidget::lineWidth() {
  138.     return _lineWidth;
  139. }
  140. int WaitingSpinnerWidget::innerRadius() {
  141.     return _innerRadius;
  142. }
  143. bool WaitingSpinnerWidget::isSpinning() const {
  144.     return _isSpinning;
  145. }
  146. void WaitingSpinnerWidget::setRoundness(qreal roundness) {
  147.     _roundness = std::max(0.0, std::min(100.0, roundness));
  148. }
  149. void WaitingSpinnerWidget::setColor(QColor color) {
  150.     _color = color;
  151. }
  152. void WaitingSpinnerWidget::setRevolutionsPerSecond(qreal revolutionsPerSecond) {
  153.     _revolutionsPerSecond = revolutionsPerSecond;
  154.     updateTimer();
  155. }
  156. void WaitingSpinnerWidget::setTrailFadePercentage(qreal trail) {
  157.     _trailFadePercentage = trail;
  158. }
  159. void WaitingSpinnerWidget::setMinimumTrailOpacity(qreal minimumTrailOpacity) {
  160.     _minimumTrailOpacity = minimumTrailOpacity;
  161. }
  162. void WaitingSpinnerWidget::rotate() {
  163.     ++_currentCounter;
  164.     if (_currentCounter >= _numberOfLines) {
  165.         _currentCounter = 0;
  166.     }
  167.     update();
  168. }
  169. void WaitingSpinnerWidget::updateSize() {
  170.     int size = (_innerRadius + _lineLength) * 2;
  171.     setFixedSize(size, size);
  172. }
  173. void WaitingSpinnerWidget::updateTimer() {
  174.     _timer->setInterval(1000 / (_numberOfLines * _revolutionsPerSecond));
  175. }
  176. void WaitingSpinnerWidget::updatePosition() {
  177.     if (parentWidget() && _centerOnParent) {
  178.         move(parentWidget()->width() / 2 - width() / 2,
  179.              parentWidget()->height() / 2 - height() / 2);
  180.     }
  181. }
  182. int WaitingSpinnerWidget::lineCountDistanceFromPrimary(int current, int primary,
  183.                                                        int totalNrOfLines) {
  184.     int distance = primary - current;
  185.     if (distance < 0) {
  186.         distance += totalNrOfLines;
  187.     }
  188.     return distance;
  189. }
  190. QColor WaitingSpinnerWidget::currentLineColor(int countDistance, int totalNrOfLines,
  191.                                               qreal trailFadePerc, qreal minOpacity,
  192.                                               QColor color) {
  193.     if (countDistance == 0) {
  194.         return color;
  195.     }
  196.     const qreal minAlphaF = minOpacity / 100.0;
  197.     int distanceThreshold =
  198.             static_cast<int>(ceil((totalNrOfLines - 1) * trailFadePerc / 100.0));
  199.     if (countDistance > distanceThreshold) {
  200.         color.setAlphaF(minAlphaF);
  201.     } else {
  202.         qreal alphaDiff = color.alphaF() - minAlphaF;
  203.         qreal gradient = alphaDiff / static_cast<qreal>(distanceThreshold + 1);
  204.         qreal resultAlpha = color.alphaF() - gradient * countDistance;
  205.         // If alpha is out of bounds, clip it.
  206.         resultAlpha = std::min(1.0, std::max(0.0, resultAlpha));
  207.         color.setAlphaF(resultAlpha);
  208.     }
  209.     return color;
  210. }
复制代码
        以上是等候提示UI控件的实当代码,大家可以根据差异的应用场景和用户需求举行扩展。    
        须要留意的是,等候提示UI控件应该在得当的机遇显示,并且要制止过长时间的等候,以免影响用户体验。同时,等候提示UI控件的样式应该简洁明白,清晰展示当前操作的状态,以便用户可以或许理解和接受。
五、利用示例

以下是一个简朴的示例代码,演示了怎样在Qt中利用此控件:
  1. #include <QCoreApplication>
  2. #include <QApplication>
  3. #include <waitingspinnerwidget.h>
  4. #include <QFrame>
  5. #include <QHBoxLayout>
  6. int main(int argc,char* argv[])
  7. {
  8.     QApplication a(argc,argv);
  9.     WaitingSpinnerWidget* spinner = new WaitingSpinnerWidget;
  10.     /// 设置waiting组件的样式
  11.     spinner->setRoundness(50.0);
  12.     spinner->setMinimumTrailOpacity(15.0);
  13.     spinner->setTrailFadePercentage(70.0);
  14.     spinner->setNumberOfLines(16);
  15.     spinner->setLineLength(15);
  16.     spinner->setLineWidth(5);
  17.     spinner->setInnerRadius(30);
  18.     spinner->setRevolutionsPerSecond(1);
  19.     spinner->setColor(QColor(81, 4, 71));
  20.     spinner->start(); // gets the show on the road!
  21.     QFrame* f = new QFrame;
  22.     QHBoxLayout* hlayout = new QHBoxLayout;
  23.     hlayout->addWidget(spinner);
  24.     f->setLayout(hlayout);
  25.     f->show();
  26.     return a.exec();
  27. }
复制代码
        总结一下,笔者分享纯代码实现等候提示UI控件的一种计划方法和流程,在此操作的基础上我们可以发挥想象开发出更多更有意思的控件,源码我放在此处以下所在。如有错误也请各位看官手下包涵,接待评论区品评指正。
        谢谢你的关注和阅读,希望我的答复能帮到你。如果还有其他题目,接待随时向我提问。祝你一切顺利!
六、源代码下载



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表