环境
Ubuntu16.04+Qt 5.7.1
目的
实现自定义图片样式的进度条
效果
素材准备
如效果图所示,可以拆分为2个部分。一是进度条,一是背景图。如
- 进度条图片;
- 背景图
代码实现
这里的加载进度使用定时器模拟数据,主要重点在于重写QWidget的paintEvent。
重写paintEvent函数
在构造函数中,成员QPixmap m_progressPixmap
先加载好图片:m_progressPixmap.load(":/progressbar.png");
void Widget::paintEvent(QPaintEvent *paintEvent)
{
Q_UNUSED(paintEvent);
//504是进度条图片的宽度;108是背景图中起始进度条的宽度;
//计算当前进度条的宽度;m_count初始化为UPPERLIMIT(100);从UPPERLIMIT减小到0时,加载完成;
//因此(UPPERLIMIT-m_count)表示的是当前的加载进度;根据图像换算出对应的宽度;
int progressWidth = (UPPERLIMIT - m_count) * (594-108) / UPPERLIMIT + 108;
//计算百分比
float percent = (UPPERLIMIT - m_count) * 100 / UPPERLIMIT;
//copy进度条样式的一小段作为绘制使用
QPixmap tempPixmap = m_progressPixmap.copy(32, 0, 44, 50);
QPainterPath progressPath;
//QPainterPath,可以绘制自定义路径。这里将其处理为圆角矩形;
//5个参数分别为x, y, w, h, roundness;
//可以注意到这里的w是变量,即加载时的进度变化;
progressPath.addRoundRect(103, 205, progressWidth, 44, 99);
QPainter painter(this);
//设置为无笔画,这里貌似写不写都无所谓;
painter.setPen(Qt::NoPen);
//设置Brush为上面的tempPixmap,即每次绘制出来都是进度条的样式;
painter.setBrush(QBrush(tempPixmap));
//设置抗锯齿
painter.setRenderHints(QPainter::Antialiasing, true);
//绘制前面定义好的QPainterPath,至此进度条绘制结束;
painter.drawPath(progressPath);
//在这里顺便把百分比显示出来,设置为蓝色笔画
painter.setPen(QPen(Qt::blue));
//设置字体大小
painter.setFont(QFont("Helvetica", 30));
//绘制文本可以采用drawText,指定x, y, QString即可;
painter.drawText(380, 240, QString("%1\%").arg(percent));
}
补充
- 主动触发paintEvent()时在这里不要使用update();而应该使用repaint();这是因为调用repaint()是及时刷新,而调用update()则是累计一定的绘画事件才会触发。因此update()的话可能会导致进度条加载看起来有点卡顿,在repaint()则会比较顺畅;
- 加载背景图的时候,最好不要使用QLabel实现,因为painter无法在QLabel上直接绘画。这里采用的QPalette实现:
QPalette palette = this->palette();
palette.setBrush(QPalette::Background, QBrush(QPixmap(":/splash.png")));
setPalette(palette);
完整代码可从此处下载。
结语
以上是Qt自定义进度条的一种实现方式。总体感觉想做出漂亮的UI效果,图片素材是绕不开的一道弯。如果以上有冗余或者不必要的逻辑,欢迎指出;如果有更好的实现方式,欢迎留言讨论。