forked from PyQt5/PyQt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgressBar.py
162 lines (135 loc) · 4.92 KB
/
ProgressBar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created on 2018年4月1日
# author: Irony
# site: https://pyqt5.com, https://github.com/892768447
# email: 892768447@qq.com
# file: ProgressBar
# description:
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
import math
from PyQt5.QtCore import QTimer, Qt, QRectF, QSize
from PyQt5.QtGui import QPainter, QPainterPath, QColor, QFont
from PyQt5.QtWidgets import QProgressBar
class ProgressBar(QProgressBar):
# 浪高百分比
waterHeight = 1
# 密度
waterDensity = 1
# 样式1为矩形, 0为圆形
styleType = 1
# 文字颜色
textColor = Qt.white
# 背景颜色
backgroundColor = Qt.gray
# 波浪颜色1
waterColor1 = QColor(33, 178, 148)
# 波浪颜色2
waterColor2 = QColor(33, 178, 148, 100)
def __init__(self, *args, **kwargs):
super(ProgressBar, self).__init__(*args, **kwargs)
self._offset = 0
# 每隔100ms刷新波浪(模拟波浪动态)
self._updateTimer = QTimer(self, timeout=self.update)
self._updateTimer.start(100)
def setRange(self, minValue, maxValue):
if minValue == maxValue == 0:
return # 不允许设置busy状态
super(ProgressBar, self).setRange(minValue, maxValue)
def setMinimum(self, value):
if value == self.maximum() == 0:
return # 不允许设置busy状态
super(ProgressBar, self).setMinimum(value)
def setMaximum(self, value):
if value == self.minimum() == 0:
return # 不允许设置busy状态
super(ProgressBar, self).setMaximum(value)
def setWaterHeight(self, height):
"""设置浪高"""
self.waterHeight = height
self.update()
def setWaterDensity(self, density):
"""设置密度"""
self.waterDensity = density
self.update()
def setStyleType(self, style):
"""设置类型"""
self.styleType = style
self.update()
def sizeHint(self):
return QSize(100, 100)
def paintEvent(self, event):
if self.minimum() == self.maximum() == 0:
return
# 正弦曲线公式 y = A * sin(ωx + φ) + k
# 当前值所占百分比
percent = 1 - (self.value() - self.minimum()) / \
(self.maximum() - self.minimum())
# w表示周期,6为人为定义
w = 6 * self.waterDensity * math.pi / self.width()
# A振幅 高度百分比,1/26为人为定义
A = self.height() * self.waterHeight * 1 / 26
# k 高度百分比
k = self.height() * percent
# 波浪1
waterPath1 = QPainterPath()
waterPath1.moveTo(0, self.height()) # 起点在左下角
# 波浪2
waterPath2 = QPainterPath()
waterPath2.moveTo(0, self.height()) # 起点在左下角
# 偏移
self._offset += 0.6
if self._offset > self.width() / 2:
self._offset = 0
for i in range(self.width() + 1):
# 从x轴开始计算y轴点
y = A * math.sin(w * i + self._offset) + k
waterPath1.lineTo(i, y)
# 相对第一条需要进行错位
y = A * math.sin(w * i + self._offset + self.width() / 2 * A) + k
waterPath2.lineTo(i, y)
# 封闭两条波浪,形成一个 U形 上面加波浪的封闭区间
waterPath1.lineTo(self.width(), self.height())
waterPath1.lineTo(0, self.height())
waterPath2.lineTo(self.width(), self.height())
waterPath2.lineTo(0, self.height())
# 整体形状(矩形或者圆形)
bgPath = QPainterPath()
if self.styleType:
bgPath.addRect(QRectF(self.rect()))
else:
radius = min(self.width(), self.height())
bgPath.addRoundedRect(QRectF(self.rect()), radius, radius)
# 开始画路径
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing, True)
# 设置没有画笔
painter.setPen(Qt.NoPen)
# 先整体绘制背景,然后再在背景上方绘制两条波浪
painter.save()
painter.setBrush(self.backgroundColor)
painter.drawPath(bgPath)
painter.restore()
# 波浪1
painter.save()
painter.setBrush(self.waterColor1)
painter.drawPath(waterPath1)
painter.restore()
# 波浪2
painter.save()
painter.setBrush(self.waterColor2)
painter.drawPath(waterPath2)
painter.restore()
# 绘制文字
if not self.isTextVisible():
return
painter.setPen(self.textColor)
font = self.font() or QFont()
font.setPixelSize(int(min(self.width(), self.height()) / 2))
painter.setFont(font)
painter.drawText(self.rect(), Qt.AlignCenter, '%d%%' %
(self.value() / self.maximum() * 100))