等候样式控件是我们在做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、头文件
- #pragma once
- #include <QWidget>
- #include <QTimer>
- #include <QColor>
- class WaitingSpinnerWidget : public QWidget {
- Q_OBJECT
- public:
- WaitingSpinnerWidget(QWidget *parent = 0,
- bool centerOnParent = true,
- bool disableParentWhenSpinning = true);
- WaitingSpinnerWidget(Qt::WindowModality modality,
- QWidget *parent = 0,
- bool centerOnParent = true,
- bool disableParentWhenSpinning = true);
- public slots:
- void start();
- void stop();
- public:
- void setColor(QColor color);
- void setRoundness(qreal roundness);//圆角
- void setMinimumTrailOpacity(qreal minimumTrailOpacity);//最小轨迹不透明度
- void setTrailFadePercentage(qreal trail);//轨迹褪色百分比
- void setRevolutionsPerSecond(qreal revolutionsPerSecond);//每秒钟转数
- void setNumberOfLines(int lines);//线条数量
- void setLineLength(int length);//线条长度
- void setLineWidth(int width);//线条宽度
- void setInnerRadius(int radius);//内圆半径
- QColor color();
- qreal roundness();
- qreal minimumTrailOpacity();
- qreal trailFadePercentage();
- qreal revolutionsPersSecond();
- int numberOfLines();
- int lineLength();
- int lineWidth();
- int innerRadius();
- bool isSpinning() const;
- private slots:
- void rotate();
- protected:
- void paintEvent(QPaintEvent *paintEvent);
- private:
- static int lineCountDistanceFromPrimary(int current, int primary,
- int totalNrOfLines);
- static QColor currentLineColor(int distance, int totalNrOfLines,
- qreal trailFadePerc, qreal minOpacity,
- QColor color);
- void initialize();
- void updateSize();
- void updateTimer();
- void updatePosition();
- private:
- QColor _color;
- qreal _roundness; // 0..100
- qreal _minimumTrailOpacity;
- qreal _trailFadePercentage;
- qreal _revolutionsPerSecond;
- int _numberOfLines;
- int _lineLength;
- int _lineWidth;
- int _innerRadius;
- private:
- WaitingSpinnerWidget(const WaitingSpinnerWidget&);
- WaitingSpinnerWidget& operator=(const WaitingSpinnerWidget&);
- QTimer *_timer;
- bool _centerOnParent;
- bool _disableParentWhenSpinning;
- int _currentCounter;
- bool _isSpinning;
- };
复制代码 2、实当代码
- #include "waitingspinnerwidget.h"
- #include <cmath>
- #include <algorithm>
- #include <QPainter>
- #include <QTimer>
- WaitingSpinnerWidget::WaitingSpinnerWidget(QWidget *parent,
- bool centerOnParent,
- bool disableParentWhenSpinning)
- : QWidget(parent),
- _centerOnParent(centerOnParent),
- _disableParentWhenSpinning(disableParentWhenSpinning) {
- initialize();
- }
- WaitingSpinnerWidget::WaitingSpinnerWidget(Qt::WindowModality modality,
- QWidget *parent,
- bool centerOnParent,
- bool disableParentWhenSpinning)
- : QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint),
- _centerOnParent(centerOnParent),
- _disableParentWhenSpinning(disableParentWhenSpinning){
- initialize();
- // We need to set the window modality AFTER we've hidden the
- // widget for the first time since changing this property while
- // the widget is visible has no effect.
- setWindowModality(modality);
- setAttribute(Qt::WA_TranslucentBackground);
- }
- void WaitingSpinnerWidget::initialize() {
- _color = Qt::black;
- _roundness = 100.0;
- _minimumTrailOpacity = 3.14159265358979323846;
- _trailFadePercentage = 80.0;
- _revolutionsPerSecond = 1.57079632679489661923;
- _numberOfLines = 20;
- _lineLength = 10;
- _lineWidth = 2;
- _innerRadius = 10;
- _currentCounter = 0;
- _isSpinning = false;
- _timer = new QTimer(this);
- connect(_timer, SIGNAL(timeout()), this, SLOT(rotate()));
- updateSize();
- updateTimer();
- hide();
- }
- void WaitingSpinnerWidget::paintEvent(QPaintEvent *) {
- updatePosition();
- QPainter painter(this);
- painter.fillRect(this->rect(), Qt::transparent);
- painter.setRenderHint(QPainter::Antialiasing, true);
- if (_currentCounter >= _numberOfLines) {
- _currentCounter = 0;
- }
- painter.setPen(Qt::NoPen);
- for (int i = 0; i < _numberOfLines; ++i) {
- painter.save();
- painter.translate(_innerRadius + _lineLength,
- _innerRadius + _lineLength);
- qreal rotateAngle =
- static_cast<qreal>(360 * i) / static_cast<qreal>(_numberOfLines);
- painter.rotate(rotateAngle);
- painter.translate(_innerRadius, 0);
- int distance =
- lineCountDistanceFromPrimary(i, _currentCounter, _numberOfLines);
- QColor color =
- currentLineColor(distance, _numberOfLines, _trailFadePercentage,
- _minimumTrailOpacity, _color);
- painter.setBrush(color);
- // TODO improve the way rounded rect is painted
- painter.drawRoundedRect(
- QRect(0, -_lineWidth / 2, _lineLength, _lineWidth), _roundness,
- _roundness, Qt::RelativeSize);
- painter.restore();
- }
- }
- void WaitingSpinnerWidget::start() {
- updatePosition();
- _isSpinning = true;
- show();
- if(parentWidget() && _disableParentWhenSpinning) {
- parentWidget()->setEnabled(false);
- }
- if (!_timer->isActive()) {
- _timer->start();
- _currentCounter = 0;
- }
- }
- void WaitingSpinnerWidget::stop() {
- _isSpinning = false;
- hide();
- if(parentWidget() && _disableParentWhenSpinning) {
- parentWidget()->setEnabled(true);
- }
- if (_timer->isActive()) {
- _timer->stop();
- _currentCounter = 0;
- }
- }
- void WaitingSpinnerWidget::setNumberOfLines(int lines) {
- _numberOfLines = lines;
- _currentCounter = 0;
- updateTimer();
- }
- void WaitingSpinnerWidget::setLineLength(int length) {
- _lineLength = length;
- updateSize();
- }
- void WaitingSpinnerWidget::setLineWidth(int width) {
- _lineWidth = width;
- updateSize();
- }
- void WaitingSpinnerWidget::setInnerRadius(int radius) {
- _innerRadius = radius;
- updateSize();
- }
- QColor WaitingSpinnerWidget::color() {
- return _color;
- }
- qreal WaitingSpinnerWidget::roundness() {
- return _roundness;
- }
- qreal WaitingSpinnerWidget::minimumTrailOpacity() {
- return _minimumTrailOpacity;
- }
- qreal WaitingSpinnerWidget::trailFadePercentage() {
- return _trailFadePercentage;
- }
- qreal WaitingSpinnerWidget::revolutionsPersSecond() {
- return _revolutionsPerSecond;
- }
- int WaitingSpinnerWidget::numberOfLines() {
- return _numberOfLines;
- }
- int WaitingSpinnerWidget::lineLength() {
- return _lineLength;
- }
- int WaitingSpinnerWidget::lineWidth() {
- return _lineWidth;
- }
- int WaitingSpinnerWidget::innerRadius() {
- return _innerRadius;
- }
- bool WaitingSpinnerWidget::isSpinning() const {
- return _isSpinning;
- }
- void WaitingSpinnerWidget::setRoundness(qreal roundness) {
- _roundness = std::max(0.0, std::min(100.0, roundness));
- }
- void WaitingSpinnerWidget::setColor(QColor color) {
- _color = color;
- }
- void WaitingSpinnerWidget::setRevolutionsPerSecond(qreal revolutionsPerSecond) {
- _revolutionsPerSecond = revolutionsPerSecond;
- updateTimer();
- }
- void WaitingSpinnerWidget::setTrailFadePercentage(qreal trail) {
- _trailFadePercentage = trail;
- }
- void WaitingSpinnerWidget::setMinimumTrailOpacity(qreal minimumTrailOpacity) {
- _minimumTrailOpacity = minimumTrailOpacity;
- }
- void WaitingSpinnerWidget::rotate() {
- ++_currentCounter;
- if (_currentCounter >= _numberOfLines) {
- _currentCounter = 0;
- }
- update();
- }
- void WaitingSpinnerWidget::updateSize() {
- int size = (_innerRadius + _lineLength) * 2;
- setFixedSize(size, size);
- }
- void WaitingSpinnerWidget::updateTimer() {
- _timer->setInterval(1000 / (_numberOfLines * _revolutionsPerSecond));
- }
- void WaitingSpinnerWidget::updatePosition() {
- if (parentWidget() && _centerOnParent) {
- move(parentWidget()->width() / 2 - width() / 2,
- parentWidget()->height() / 2 - height() / 2);
- }
- }
- int WaitingSpinnerWidget::lineCountDistanceFromPrimary(int current, int primary,
- int totalNrOfLines) {
- int distance = primary - current;
- if (distance < 0) {
- distance += totalNrOfLines;
- }
- return distance;
- }
- QColor WaitingSpinnerWidget::currentLineColor(int countDistance, int totalNrOfLines,
- qreal trailFadePerc, qreal minOpacity,
- QColor color) {
- if (countDistance == 0) {
- return color;
- }
- const qreal minAlphaF = minOpacity / 100.0;
- int distanceThreshold =
- static_cast<int>(ceil((totalNrOfLines - 1) * trailFadePerc / 100.0));
- if (countDistance > distanceThreshold) {
- color.setAlphaF(minAlphaF);
- } else {
- qreal alphaDiff = color.alphaF() - minAlphaF;
- qreal gradient = alphaDiff / static_cast<qreal>(distanceThreshold + 1);
- qreal resultAlpha = color.alphaF() - gradient * countDistance;
- // If alpha is out of bounds, clip it.
- resultAlpha = std::min(1.0, std::max(0.0, resultAlpha));
- color.setAlphaF(resultAlpha);
- }
- return color;
- }
复制代码 以上是等候提示UI控件的实当代码,大家可以根据差异的应用场景和用户需求举行扩展。
须要留意的是,等候提示UI控件应该在得当的机遇显示,并且要制止过长时间的等候,以免影响用户体验。同时,等候提示UI控件的样式应该简洁明白,清晰展示当前操作的状态,以便用户可以或许理解和接受。
五、利用示例
以下是一个简朴的示例代码,演示了怎样在Qt中利用此控件:
- #include <QCoreApplication>
- #include <QApplication>
- #include <waitingspinnerwidget.h>
- #include <QFrame>
- #include <QHBoxLayout>
- int main(int argc,char* argv[])
- {
- QApplication a(argc,argv);
- WaitingSpinnerWidget* spinner = new WaitingSpinnerWidget;
- /// 设置waiting组件的样式
- spinner->setRoundness(50.0);
- spinner->setMinimumTrailOpacity(15.0);
- spinner->setTrailFadePercentage(70.0);
- spinner->setNumberOfLines(16);
- spinner->setLineLength(15);
- spinner->setLineWidth(5);
- spinner->setInnerRadius(30);
- spinner->setRevolutionsPerSecond(1);
- spinner->setColor(QColor(81, 4, 71));
- spinner->start(); // gets the show on the road!
- QFrame* f = new QFrame;
- QHBoxLayout* hlayout = new QHBoxLayout;
- hlayout->addWidget(spinner);
- f->setLayout(hlayout);
- f->show();
- return a.exec();
- }
复制代码 总结一下,笔者分享纯代码实现等候提示UI控件的一种计划方法和流程,在此操作的基础上我们可以发挥想象开发出更多更有意思的控件,源码我放在此处以下所在。如有错误也请各位看官手下包涵,接待评论区品评指正。
谢谢你的关注和阅读,希望我的答复能帮到你。如果还有其他题目,接待随时向我提问。祝你一切顺利!
六、源代码下载
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |