
最近收到了新的需求,让我们制作一个动态进度条.
由于我们的产品比较大,因此启动该软件需要花费较长的时间. 本机进度栏不能再满足我们的需求. 在这里,我们需要一个移动的进度栏. 效果如下图所示.
灯光效果进度条主要是制作进度,并在完成的部分上快速迭代渲染,给用户直观的感觉. 我们的软件一直在努力加载c#进度条更改颜色,并且仍然有效.

有了这个进度条,当我们的进度从40%增长到50%时,该界面将不再显得暂停,这是完美的吗? .
让我分析一下动态进度条的完成方式
如效果图所示,灯光效果进度条与常规进度条不同. 他还在基本任务进度的基础上增加了一层灯光效果c#进度条更改颜色,主要是告诉用户我们的软件一直在努力工作,请耐心等待.
当我自己创建函数时,我经常喜欢先进行测试演示,然后将完成的函数集成到正式环境中. 此功能未列出. 第一部分中显示的效果图是测试. 尽管该演示看起来很丑陋,但其中包含一些基本功能.
许多软件现在在进度显示中具有更华丽的效果. 例如,当压缩软件并解压缩文件时,将有一个动态进度条. 使用过它的学生应该知道它的外观,并且我们的灯光效果进度条与此效果类似. 此外,我们还提供另一种运动效果,即延迟运动效果. 两者在一定程度上都显示出更友好的进步效果.
在启动分析功能之前,首先,考虑一下我们的需求: 动态进度条,这意味着需要将实时添加到原始进度条中,以使进度条看起来更酷,除了灯光效果进度条之外,还有一个延迟进度条,它也是一个动态进度条.
延迟运动效果并保持直截了当会延迟其到达. 当我们将进度从10%设置为20%时,程序会模拟一个渐进过程并使用一段时间来完成10%进度.
在这里,我们分别介绍这两个进度条的实现
要达到一个不错的进度条,我们可以从QWidget定制开始编写,也就是说从头开始,但是通常我们不这样做,因为这可能会编写出无数的bug,并且现有的轮子已经非常如果稳定,为什么要构建它?
1. 灯光效果进度条
灯光效果进度条我们使用了一些技巧来以简单的方式实现它. 我们的灯光效果进度条控件继承自Qt的本机进度条类QProgressBar. 在新类中,我们只需要在Qt中绘制本机进度,在本文结束后,您就可以制作了.
a,paintEvent函数
paintEvent函数是Qt绘制函数. 刷新接口后,将调用此接口函数,因此我们需要重写此接口,首先调用父窗口的绘图方法,然后绘制自己的,代码如下
QProgressBar::paintEvent(event); drawCache绘制动效
b,drawCache绘制效果

绘制运动效果时,我们需要知道运动效果的绘制区域. 在这个地方,我们需要积极分析qss的一些参数. Qt的style()-> subElementRect接口可以获取我们所需的信息.
p>
以下是我们实施过程的简要说明
•首先,我们获取进度条的几何尺寸和中间进度的几何尺寸,以便我们可以计算每个边框的值
•根据当前值,我们可以计算已通过的进度条的几何尺寸(即,该值小于我们设置的面积)
•我们的灯光效果是在第二步中计算出的区域上运行,并一直进行迭代
•我们在内存中维护一个cacheValue. 每次刷新接口时,此值都会增加,但不能大于第二步中的值. cacheValue将是我们绘图的关键参数. 他代表绘图. 长度
•构造渐变画笔并将其设置为QPainter
•绘制效果
上下通常描述绘制效果的过程. 具体代码发送如下. 由于篇幅所限,我已经处理了一些伪代码.
void GMPProgressBar::drawCache()
{
QStyleOptionProgressBarV2 opt;
QRect outerRect = style()->subElementRect(QStyle::SE_ProgressBarGroove, &opt, this);
QRect innerRect = style()->subElementRect(QStyle::SE_ProgressBarContents, &opt, this);
QMargins borders(构造一个QMargins);
QRectF rect(运动效果图区域);
if (m_iCacheValue != 0)
{
QPainter painter(this);
QLinearGradient gradient(构造绘图刷子);
painter.setBrush(gradient);
painter.drawRoundedRect(rect, 2, 2);
}
}
c,定期刷新
由于需要主动刷新,因此我们需要声明一个计时器,然后定期刷新它. 实现代码可能类似于以下内容
connect(m_pCacheTimer, &QTimer::timeout, this, [this]{
if (TM_CACHE == m_mode)
{
++m_iCacheValue;
repaint();
}else
{
m_pCacheTimer->stop();
}
});
仅当我们第一次设置进度条值时,或者当我们设置新值并且计时器没有启动时,我们才需要启动计时器.
TM_CACHE模式是我们的模式,TM_SMOOTH模式是我们的延迟到达模式
connect(this, &QProgressBar::valueChanged, [this](int value){//TM_CACHE模式下 启动时机
if (!m_pCacheTimer->isActive() && value != 0 && TM_CACHE == m_mode)
{
m_pCacheTimer->start(m_iRefreshleveling);
}
});

动态进度栏的效果如下图所示

2. 进度栏延迟
进度条可能更适合启动界面,但是有时候我们可能需要更平滑的加载曲线,例如在安装软件或卸载软件时.
a,setValue
延迟到达进度栏和动态进度栏的实现方式不同. 对于延迟到达进度栏,我们在此处重写了setValue函数. 当外部调用此接口设置值时,我们没有立即设置当前值,而是花了一段时间来完成此值得刷新的操作.
•在外部调用setValue时,我们首先计算应绘制PixelMax的最大宽度,已绘制的最大宽度cacheValue以及步长
•设置计时器刷新频率并重新启动计时器
•刷新计时器时,cacheValue会增加步长
•调用父类的QProgressBar :: setValue接口以设置值
b,计时器
达到延迟功能的计时器可以与我们之前使用的计时器混合使用. 刷新计时器时,可以为不同的模式执行不同的代码. 实现代码可能像下面这样
connect(m_pCacheTimer, &QTimer::timeout, this, [this]{
if (TM_CACHE == m_mode)
{
++m_iCacheValue;
repaint();
}
else if (TM_SMOOTH == m_mode)
{
changeSmooth();
}
else
{
m_pCacheTimer->stop();
}
});
延迟到达进度栏的效果如下所示:

3. 界面说明
灯光效果进度条类仅向外界公开三个界面,分别设置模式,持续时间和刷新频率
特别要注意的是,我们在这里重写了父类的setValue接口,这意味着我们不能使用多态来操纵此接口
void setTransitionMode(TransitionMode mode);//设置模式 void setSmoothDuration(int duration);//设置刷新总时长 模式为TM_SMOOTH时有效 void setRefreshleveling(int rate);//设置刷新频率 每次更改TransitionMode之后会变为默认值

a. 修改模式
修改模式时,我们需要清除内存中的所有数据并将其值设置为0.
void GMPProgressBar::setTransitionMode(TransitionMode mode)
{
if (m_mode == mode)
{
return;
}
m_mode = mode;
clearData();
QProgressBar::setValue(0);
}
b,其他界面
设置刷新时间和频率界面相对简单,无需特殊说明
特别注意: 最好在开始之前设置三个界面,尝试在开始之后不要调用
在第二部分中,我们主要讨论了如何制作动态进度条. 在本节中,我们将创建一个启动页面并使用这种动态效果.
启动图不是我们的主要分析对象,我将简要讨论该类的实现和一些借口
1. 实施思路
Qt为我们提供了QSplashScreen,但是它的使用仍然非常有限,因此在这里我直接开发了Qt源代码以进行二次开发
•首先,Qt的本机实现基本上已被移植
•启动图使用简单的顶部和底部布局. 上面的图片是一张自画的图片,放在QLabel上,进度条在下面
•自绘图片包括产品名称,徽标,背景图片等.
2. 背景图片切换
调用setPixmap设置背景图像时,如果指定多个图像,我将启动一个计时器,在指定的持续时间后重建一个大的背景图像,并将其添加到启动窗口中
这里我们主要说明背景图片的构造方法,代码如下
a. 根据背景图像构造启动图像的大小,然后将其移至屏幕中间
m_currentPixmap = m_lstPixmaps.at(m_iCurrentIndex); QRect size(QPoint(), m_currentPixmap.size() / m_currentPixmap.devicePixelRatio()); size.setHeight(size.height() + StatusBarHeight); setFixedSize(size.size()); m_pProgressBar->setFixedWidth(size.width() / 8 * 3); move(QApplication::desktop()->screenGeometry().center() - size.center());
b. 绘制程序徽标

QPainter painter(&m_currentPixmap); painter.drawPixmap(m_startPos, m_logo);
c,绘制标题栏
painter.save(); painter.setFont(m_titleFont); QFontMetrics fontMetrics(m_titleFont); int textWidth = fontMetrics.width(m_strWindowTitle); int textHegith = m_logo.height(); QRect textTect = QRect(m_startPos + QPoint(13 + m_logo.width(), 0), QSize(textWidth, textHegith)); painter.drawText(textTect, m_strWindowTitle, QTextOption(Qt::AlignCenter)); painter.restore();
d. 设置为QLabel背景图片
m_pWindowBackground-> setPixmap(m_currentPixmap);
启动图像的效果不再是此处的标签. 第三部分中的两个gif图片是最终的启动图片效果
最后是测试代码,主要模拟程序的加载过程
1. 施工启动图
首先,我们构造一个启动图对象,并设置程序徽标和模式
GMPSplashScreen * screen = new GMPSplashScreen(QPixmap(":/splashScreen/start.png"));
screen->show();
screen->setLogo(QIcon("logo.ico").pixmap(48, 48));
screen->setTransitionMode(GMPProgressBar::TM_CACHE);
2. 背景图片
设置背景图片,并设置背景图片更换间隔
QList<QPixmap> lstPixmap;
lstPixmap.append(QPixmap(":/splashScreen/start.png"));
lstPixmap.append(QPixmap(":/splashScreen/start.jpg"));
screen->setPixmap(lstPixmap, 2000);
3. 其他信息
设置程序的提示信息和标题栏
screen->showMessage("Established connections", 0);
screen->setTitle(QStringLiteral("广联达BIM土建计量GTJ2018"));
4. 事件循环
这里编写了一个无限循环,主要是模拟程序的加载过程,并每10ms处理一次接口刷新事件
a.processEvents();
while (1)
{
QTest::qSleep(10);
a.processEvents();
}
splashScreen w;
w.show();
screen->finish(&w);
摘要
以上是编辑器向您介绍的酷启动图表动态进度条效果的C#实现. 希望对大家有帮助. 如有任何疑问,请给我留言,编辑会及时给您答复!
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-226972-1.html
正解