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

         等待样式控件是我们在做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更新绘制达到转圈圈的效果。

二、 设计思路   
  1. 创建一个QWidget派生的自定义控件,用于显示等待提示。
  2. 在自定义控件中,绘制一个圆形的等待图标。
  3. 通过重写paintEvent函数,在paintEvent中绘制等待图标。
  4. 利用定时器QTimer并实现一个槽函数来更新图标。
  5. 在槽函数中调用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..100qreal   _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 paintedpainter.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控件的一种设计方法和流程,在此操作的基础上我们可以发挥想象开发出更多更有意思的控件,源码我放在此处以下地址。如有错误也请各位看官手下留情,欢迎评论区批评指正。

        谢谢你的关注和阅读,希望我的回答能帮到你。如果还有其他问题,欢迎随时向我提问。祝你一切顺利!

六、源代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/47075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot下的定时魔法:揭秘@Scheduled注解的无限可能

在这个快节奏的时代&#xff0c;自动化与定时任务成为了提升效率的不二法门。而在Java的Spring Boot框架中&#xff0c;Scheduled注解就像是一位精通时间魔法的巫师&#xff0c;悄无声息地让你的应用按部就班地执行着各种定时任务。今天&#xff0c;就让我们一起揭开它的神秘面…

Ubuntu上安装配置samba服务

Ubuntu上安装配置samba服务 在Ubuntu中安装配置samba共享服务&#xff0c;可以让你在网络上共享文件和打印机。以下是一个相对详细的步骤指南&#xff0c;介绍如何在Ubuntu上安装和配置Samba。 1. 安装Samba 首先&#xff0c;需要安装Samba软件包。打开终端并运行以下命令&a…

Gocator Acquisition for Cognex VisionPro(LMI相机图像获取)

概述 VisionPro 是个很强大的视觉软件, 我们很乐意我们的客户在VisionPro 环境中使用Gocator产品。 实现方法 在 VisionPro 环境下配置 Gocator 产品两种方法: ● 方法一: 创建一个 QuickBuild Job,在 Job 编辑器添加 Job Script,插入 Gocator 的 SDK,编辑简 单脚本就 OK。 …

八、golang基础之reflect反射

文章目录 一、interface 和 反射二、Golang的反射reflect&#xff08;一&#xff09;reflect的基本功能TypeOf和ValueOf&#xff08;二&#xff09;从relfect.Value中获取接口interface的信息&#xff08;三&#xff09;未知原有类型【遍历探测其Filed】&#xff08;四&#xf…

在 Node.js 中使用 axios 配置代理并实现图片并发下载

文章目录 一、创建 Axios 实例二、图片并发下载三、参考资料 一、创建 Axios 实例 可以创建一个 axiosConfig.ts 文件用于创建和更新相关实例&#xff1a; // server/utils/axiosConfig.ts const axios require("axios"); const { HttpsProxyAgent } require(htt…

java.lang.IllegalArgumentException: Illegal character in path at index 40解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

K最近邻(K-Nearest Neighbors, KNN)

K最近邻&#xff08;K-Nearest Neighbors, KNN&#xff09;理论知识推导 KNN算法是一个简单且直观的分类和回归方法&#xff0c;其基本思想是&#xff1a;给定一个样本点&#xff0c;找到训练集中与其最近的K个样本点&#xff0c;根据这些样本点的类别&#xff08;分类问题&am…

Ubuntu 22.04.4 LTS (linux) 安装iftop 监控网卡流量 软件

1 安装iftop sudo apt update sudo apt-get install iftop 2 监控网卡 sudo iftop -i eth0 -n -p 界面最上面&#xff0c;显示的是类似刻度尺的刻度范围&#xff0c;显示流量图形的长条作标尺用的。 中间的< >这两个左右箭头&#xff0c;表示的是流量的进出方向.TX&…

PTA - 嵌套列表求和

使用递归函数对嵌套列表求和 函数接口定义&#xff1a; def sumtree(L) L是输入的嵌套列表。 裁判测试程序样例&#xff1a; /* 请在这里填写答案 */L eval(input()) print(sumtree(L)) # 调用函数 输入样例&#xff1a; 在这里给出一组输入。例如&#xff1a; [1,[2…

邮件飞鸿:深入解析Laravel的邮件系统

邮件飞鸿&#xff1a;深入解析Laravel的邮件系统 在现代Web应用中&#xff0c;邮件服务是与用户交互的重要方式之一。Laravel&#xff0c;作为PHP界的流行框架&#xff0c;提供了一个强大而灵活的邮件系统。本文将深入探讨Laravel的邮件系统如何工作&#xff0c;并通过代码示例…

轻断食1.0.1-july 16th 冥想1.1.1

自己昨天晚上吃了豆皮以后&#xff0c;自己感觉自己还是很饿&#xff0c;然后随即自己又吃了一些东西&#xff08;其实自己可以控制的&#xff0c;但是没有办法&#xff0c;你不知道那种感觉&#xff1a;有一只该死的蚊子&#xff0c;老在自己的耳朵旁边嗡嗡乱飞。&#xff09;…

Python中的sorted()与list.sort():深入解析它们的效率差异

目录 Python中的sorted()与list.sort()&#xff1a;深入解析它们的效率差异内部实现与原理sorted()list.sort() 性能与内存使用内存消耗执行速度适用场景sorted()list.sort() 实例对比结论 Python中的sorted()与list.sort()&#xff1a;深入解析它们的效率差异 在Python编程中…

【Vue随笔】Vue中watch的不同写法

【写在前面】在实际开发中&#xff0c;我们要监听的属性可能是对象中的某个属性&#xff0c;除了对整个对象进行监听以外&#xff0c;我们可以用单引号包裹的形式监听对象中的某个属性。 watch: {searchFormModel.appKey: function (newVal) {if (newVal.includes(全部)) {if (…

昇思25天学习打卡营第23天|基于MindSpore的GPT2文本摘要

这节课主要学习基于MindSpore的GPT2文本摘要。主要包括环境安装、数据集加载与处理、模型构建、模型训练、模型推理五部分内容。 1.首先介绍环境安装 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面…

go 编译ollama的时候报错:open /dev/null: no such file or directory

go 编译ollama的时候报错&#xff1a;open /dev/null: no such file or directory github.com/xtgo/set: /root/work/go/pkg/tool/linux_amd64/compile: open /dev/null: no such file or directory gonum.org/v1/gonum/blas/gonum: /root/work/go/pkg/tool/linux_amd64/compi…

Spark中的JOIN机制

Spark中的JOIN机制 1、Hash Join概述2、影响JOIN的因素3、Spark中的JOIN策略3.1、Shuffle Hash Join3.2、Broadcast Hash Join3.3、Sort Merge Join3.4、Cartesian Product Join2.5、Broadcast Nested Loop Join1、Hash Join概述 Apache Spark共提供了五种JOIN机制,其中常用的…

Laravel Horizon:任务队列的智能指挥官

Laravel Horizon&#xff1a;任务队列的智能指挥官 在现代Web应用中&#xff0c;处理耗时的任务通常需要异步执行&#xff0c;以避免阻塞主线程和影响用户体验。Laravel的Horizon任务系统是一个强大的后台工作管理器&#xff0c;它不仅优化了队列任务的处理&#xff0c;还提供…

【论文阅读】MCTformer+:弱监督语义分割的多类令牌转换器

【论文阅读】MCTformer:弱监督语义分割的多类令牌转换器 文章目录 【论文阅读】MCTformer:弱监督语义分割的多类令牌转换器一、介绍1.1 WSSS背景1.2 WSSS策略 二、联系工作2.1 弱监督语义分割2.2 transformers的可视化应用 三、MULTI-CLASS TOKEN TRANSFORMER3.1 Multi-class t…

读人工智能全传15意向立场

1. 物理立场 1.1. 可以解释一个实体行为 1.2. 在物理立场中&#xff0c;我们使用自然法则(物理、化学等)来预测系统的行为结果 1.3. 虽然物理立场在解释这种行为的时候非常有效&#xff0c;但无法应用于理解或者预测人类行为 1.3.1. …

java基础学习:序列化之 - hessian2

文章目录 一、介绍二、主要特点三、应用场景四、使用方式五、与其他序列化协议的比较六、总结 一、介绍 Hessian2是Hessian协议的一个更新版本&#xff0c;由Caucho Technology公司开发。Hessian是一种基于二进制的轻量级、高效的跨语言序列化协议。Hessian2相较于原始Hessian…