PySide2/PyQt5练习:用QPainter绘制环形进度条

好久没写Python了,拿Qt来练习下Python。代码很简单,就是绘制一个环形的滚动条,带动画和渐变效果。动画使用的QTimeLine,渐变使用的QConicalGradient径向渐变。每次修改角度值时,就启动timeline,实现动画效果。

写的过程中遇到了一些问题:一是Qt径向渐变默认是逆时针的,解决办法是使用QPainter的setViewport把视口翻转一下;二是PyQt5无法把QRect隐式转换为QRectF,在PySide2中就可以,没办法,最后就用的QRectF,代码通用一点;(2020-1-2补充)三是QTimeLine start() 前需要先确保上一次动作已经结束,所以现在我start前显式调用了一次stop。

效果如下:

代码如下:

import sys
# 懒得一个一个的写
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
# 如果是pyqt5用下面的import
#from PyQt5.QtCore import *
#from PyQt5.QtWidgets import *
#from PyQt5.QtGui import *
 
class CircularProgress(QWidget):
    def __init__(self):
        super().__init__()
        # 记录角度
        self.angle=90
        # 这个是用于绘制的,angle才是真实的角度
        self.drawAngle=self.angle
        # 进度条宽度
        self.lineWidth=20
        # 时间线做动画
        self.timeLine=QTimeLine(1000,self)
        self.timeLine.frameChanged.connect(self.updateTimeline)
 
        # 数字输入框
        self.input=QSpinBox(self)
        self.input.setRange(0,360)
        self.input.setValue(45)
        self.input.setGeometry(10,10,90,30)
        # 按钮
        self.btn=QPushButton("Set",self)
        self.btn.setGeometry(10,45,90,30)
        self.btn.clicked.connect(self.setAngle)
        # 透明样式
        self.setStyleSheet("QSpinBox,QPushButton{background:transparent;border:1px solid black;}")
 
    def updateTimeline(self,frame):
        self.drawAngle=frame
        self.update()
 
    def setAngle(self):
        self.drawAngle=self.angle
        self.angle=self.input.value()
        self.timeLine.stop()
        self.timeLine.setFrameRange(self.drawAngle,self.angle)
        # self.update()
        self.timeLine.start()
 
    def paintEvent(self,event):
        # 这里有个问题是,pyqt5无法隐式吧QRect转为QRectF(PySide2可以),所以这里直接用QRectF
        the_rect=QRectF(0,0,self.width(),self.height())
        if the_rect.isNull():
            return
        # 画笔
        painter=QPainter(self)
        painter.fillRect(the_rect,QColor("darkCyan"))
        painter.setRenderHints(QPainter.Antialiasing|QPainter.SmoothPixmapTransform,on=True)
        # 镜像翻转,这样就是顺时针
        painter.setViewport(self.width(),0,-self.width(),self.height())
 
        # path默认OddEvenFill,这样就填充两个圆相交的部分
        the_path=QPainterPath()
        the_path.addEllipse(the_rect.adjusted(1,1,-1,-1))
        the_path.addEllipse(the_rect.adjusted(
            1+self.lineWidth,1+self.lineWidth,-1-self.lineWidth,-1-self.lineWidth))
        painter.fillPath(the_path,QColor(6,79,103))
 
        # 径向渐变(参数为中心点和起始角度),默认时从右侧开始逆时针算的
        the_gradient=QConicalGradient(the_rect.center(),90)
        the_angle=self.drawAngle/360
        the_gradient.setColorAt(0,QColor(255,255,0));
        the_gradient.setColorAt(the_angle,QColor(255,0,255));
        if the_angle+0.001<1:
            the_gradient.setColorAt(the_angle+0.001,QColor(0,0,0,0));
        painter.fillPath(the_path,the_gradient);
 
 
 
if __name__=="__main__":
    app=QApplication(sys.argv)
    w=CircularProgress()
    w.setWindowTitle("龚建波 1992")
    w.resize(400,400)
    w.show()
    sys.exit(app.exec_())
发布了95 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/103571569