前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PyQt5渐变圆环水波进度条+透明淡入(多线程信号)

PyQt5渐变圆环水波进度条+透明淡入(多线程信号)

作者头像
zmh-program
发布2023-02-06 09:57:47
1.1K0
发布2023-02-06 09:57:47
举报
文章被收录于专栏:信息技术博客

上效果:

![Deskto

文章目录

| 导入模块

代码语言:javascript
复制
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import math

| 效果

1.线程内修改界面

参考文章https://blog.csdn.net/avatarhhh/article/details/105540255 线程内修改, PyQt5提供了信号 PyQt5.QtCore.QThread

代码语言:javascript
复制
class ProgressThread(QThread):
    signal = pyqtSignal()

    def run(self):
        for p in range(100):
            self.signal.emit()
            self.msleep(100)

其实,如果不是准时设置, 你也可以不重写run函数, 直接调用signal.emit方法即可

2. 窗口淡入(淡出)

参考文章https://blog.csdn.net/weixin_52132159/article/details/122549237… 直接写了个方法, 直接调用即可, anim类要绑定或保存在一个全局或类变量中, 在单独的函数结束中anim会直接执行__del__()方法

代码语言:javascript
复制
def Animation(parent, type=b"windowOpacity", from_value=0, to_value=1, ms=1000, connect=None):
    anim = QPropertyAnimation(parent, type)
    anim.setDuration(ms)
    anim.setStartValue(from_value)
    anim.setEndValue(to_value)
    if connect:
        anim.finished.connect(connect)
    anim.start()
    return anim

3.窗口去边框

代码语言:javascript
复制
self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框

4.透明

代码语言:javascript
复制
self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明

5.圆环进度条实现

注意!!! ShareTechMomo不是本机字体(放上Consolas可以),自行下载!

参考文章,在此基础上添加了不少东西https://blog.csdn.net/weixin_41611054/article/details/103660845

代码语言:javascript
复制
class RoundProgress(QWidget):
    m_waterOffset = 0.05
    m_offset = 50
    bg_color = QColor(255, 0, 0)
    fsize = 10
    def __init__(self, t, parent=None):
        super(RoundProgress, self).__init__(parent)
        self.resize(*t)
        self.size = t
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.percent = 0
        self.pen = QPen()
        gradient = QConicalGradient(50, 50, 91)
        gradient.setColorAt(0, QColor(255, 10, 10))
        gradient.setColorAt(1, QColor(255, 201 ,14))
        #gradient.setColorAt(0.5, QColor(255, 201 ,14))
        self.pen.setBrush(gradient)  # 设置画刷渐变效果
        self.pen.setWidth(8)
        self.pen.setCapStyle(Qt.RoundCap)
        self.font = QFont()
        self.font.setFamily("Consolas") #Share-TechMono
        self.font.setPointSize(self.size[0] // 4)
    def paintEvent(self, event):
        width, height = self.size
        rect = QRectF(self.fsize, self.fsize, width-self.fsize*2, height-self.fsize*2)
        painter = QPainter(self)
        rotateAngle = 360 * self.percent / 100
        # 绘制准备工作,启用反锯齿
        painter.setRenderHints(QPainter.Antialiasing)
        painter.setPen(self.pen)


        painter.drawArc(rect, (90 - 0) * 16, -rotateAngle * 16)  # 画圆环
        painter.setFont(self.font)
        painter.setPen(QColor(153 - 1.53*self.percent ,
                              217-0.55*self.percent,
                              234-0.02*self.percent)) # r:255, g:201 - 10/100 * percent, b: 14-4 /100*percent 当前渐变
        painter.drawText(rect, Qt.AlignCenter, "%d%%" % self.percent ) # 显示进度条当前进度
        self.update()
    def update_percent(self, p):
        self.percent = p

Qpainter画弧

6.水波进度条(正弦函数)

参考文章 https://blog.csdn.net/weixin_42512684/article/details/105227816…, 主要是我把QPainterPath裁剪成了圆形.

代码语言:javascript
复制
class WaterProgress(QWidget):
    fsize = 10
    def __init__(self,t,parent=None):
        super(WaterProgress, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.resize(*t)
        self.size = t
        self.layout = QGridLayout(self)

        #设置进度条颜色
        self.bg_color = QColor("#95BBFF")
        self.m_waterOffset = 0.005
        self.m_offset = 50
        self.m_borderwidth = 10
        self.percent = 0
    def paintEvent(self, event):
        painter = QPainter()
        painter.setRenderHint(QPainter.Antialiasing)
        painter.begin(self)
        painter.setPen(Qt.NoPen)
        #获取窗口的宽度和高度
        width,height = self.size
        percentage = 1 - self.percent/100
        # 水波走向:正弦函数 y = A(wx+l) + k
        # w 表示 周期,值越大密度越大
        w = 2 * math.pi / (width)
        # A 表示振幅 ,理解为水波的上下振幅
        A = height * self.m_waterOffset
        # k 表示 y 的偏移量,可理解为进度
        k = height *percentage


        water1 = QPainterPath()
        water2 = QPainterPath()
        #起始点
        water1.moveTo(5,height)
        water2.moveTo(5,height)
        self.m_offset += 0.6

        if(self.m_offset >(width/2)):
            self.m_offset = 0
        i = 5

        rect = QRectF(self.fsize,self.fsize,width - self.fsize*2, height - self.fsize * 2)
        while(i < width-5):
            waterY1 = A*math.sin(w*i +self.m_offset ) + k
            waterY2 = A*math.sin(w*i + self.m_offset + width/2*w) + k

            water1.lineTo(i, waterY1)
            water2.lineTo(i, waterY2)
            i += 1

        water1.lineTo(width-5,height)
        water2.lineTo(width-5,height)

        totalpath = QPainterPath()
        #totalpath.addRect(rect)
        #painter.setBrush(Qt.gray)
        painter.drawRect(self.rect())
        painter.save()
        totalpath.addEllipse(rect)
        totalpath.intersected(water1)
        painter.setPen(Qt.NoPen)

        #设置水波的透明度
        watercolor1 =QColor(self.bg_color)
        watercolor1.setAlpha(100)
        watercolor2 = QColor(self.bg_color)
        watercolor2.setAlpha(150)
        path = totalpath.intersected(water1)
        painter.setBrush(watercolor1)
        painter.drawPath(path)


        path = totalpath.intersected(water2)
        painter.setBrush(watercolor2)
        painter.drawPath(path)
        painter.restore()
        painter.end()
        #self.update()
    def update_percent(self, p):
        self.percent = p
        if self.m_waterOffset < 0.05:
            self.m_waterOffset += 0.001
        return p

7.汇入Dialog

哈哈, 这里就没参考文章了.

代码语言:javascript
复制
class Progress(QDialog):
    percent = 0
    def __init__(self, text="",parent=None):
        super(Progress, self).__init__(parent)
        Font = QFont()
        Font.setFamily("Consolas")
        Font.setPointSize(12)
        self.setFont(Font)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.ProgressThread = ProgressThread()
        self.ProgressThread.signal.connect(self.percentUpdate)
        self.ProgressThread.start()
        width, height = 230, 230
        self.resize(width, height)
        self.water = WaterProgress((width, height), self)
        self.round = RoundProgress((width, height), self)
        self.label = QLabel(self)
        self.label.setText(QCoreApplication.translate("Dialog", text))
        print(self.label.width())
        self.label.move((width-self.label.width())/2, height/3*2)
        QMetaObject.connectSlotsByName(self)
        self.anim = Animation(self, )
    def connect(self, link):
        print(type(link))
        #self.setWindowFlags(Qt.WindowStaysOnTopHint) #置顶
        self.show()
    def percentUpdate(self):
        self.percent += 1
        self.water.update_percent(self.percent)
        self.water.paintEvent(None)
        self.round.update_percent(self.percent)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    r = Progress("<a link='b'>write something</a>")
    r.show()
    sys.exit(app.exec_())

| 全部代码

一个个粘贴太麻烦了, 直接给你汇总了:

代码语言:javascript
复制
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import math
def Animation(parent, type=b"windowOpacity", from_value=0, to_value=1, ms=1000, connect=None):
    anim = QPropertyAnimation(parent, type)
    anim.setDuration(ms)
    anim.setStartValue(from_value)
    anim.setEndValue(to_value)
    if connect:
        anim.finished.connect(connect)
    anim.start()
    return anim
class ProgressThread(QThread):
    signal = pyqtSignal()

    def run(self):
        for p in range(100):
            self.signal.emit()
            self.msleep(100)
class RoundProgress(QWidget):
    m_waterOffset = 0.05
    m_offset = 50
    bg_color = QColor(255, 0, 0)
    fsize = 10
    def __init__(self, t, parent=None):
        super(RoundProgress, self).__init__(parent)
        self.resize(*t)
        self.size = t
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.percent = 0
        self.pen = QPen()
        gradient = QConicalGradient(50, 50, 91)
        gradient.setColorAt(0, QColor(255, 10, 10))
        gradient.setColorAt(1, QColor(255, 201 ,14))
        #gradient.setColorAt(0.5, QColor(255, 201 ,14))
        self.pen.setBrush(gradient)  # 设置画刷渐变效果
        self.pen.setWidth(8)
        self.pen.setCapStyle(Qt.RoundCap)
        self.font = QFont()
        self.font.setFamily("Share-TechMono") #Share-TechMono
        self.font.setPointSize(self.size[0] // 4)
    def paintEvent(self, event):
        width, height = self.size
        rect = QRectF(self.fsize, self.fsize, width-self.fsize*2, height-self.fsize*2)
        painter = QPainter(self)
        rotateAngle = 360 * self.percent / 100
        # 绘制准备工作,启用反锯齿
        painter.setRenderHints(QPainter.Antialiasing)
        painter.setPen(self.pen)


        painter.drawArc(rect, (90 - 0) * 16, -rotateAngle * 16)  # 画圆环
        painter.setFont(self.font)
        painter.setPen(QColor(153 - 1.53*self.percent ,
                              217-0.55*self.percent,
                              234-0.02*self.percent)) # r:255, g:201 - 10/100 * percent, b: 14-4 /100*percent 当前渐变
        painter.drawText(rect, Qt.AlignCenter, "%d%%" % self.percent ) # 显示进度条当前进度
        self.update()
    def update_percent(self, p):
        self.percent = p
class WaterProgress(QWidget):
    fsize = 10
    def __init__(self,t,parent=None):
        super(WaterProgress, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.resize(*t)
        self.size = t
        self.layout = QGridLayout(self)

        #设置进度条颜色
        self.bg_color = QColor("#95BBFF")
        self.m_waterOffset = 0.005
        self.m_offset = 50
        self.m_borderwidth = 10
        self.percent = 0
    def paintEvent(self, event):
        painter = QPainter()
        painter.setRenderHint(QPainter.Antialiasing)
        painter.begin(self)
        painter.setPen(Qt.NoPen)
        #获取窗口的宽度和高度
        width,height = self.size
        percentage = 1 - self.percent/100
        # 水波走向:正弦函数 y = A(wx+l) + k
        # w 表示 周期,值越大密度越大
        w = 2 * math.pi / (width)
        # A 表示振幅 ,理解为水波的上下振幅
        A = height * self.m_waterOffset
        # k 表示 y 的偏移量,可理解为进度
        k = height *percentage


        water1 = QPainterPath()
        water2 = QPainterPath()
        #起始点
        water1.moveTo(5,height)
        water2.moveTo(5,height)
        self.m_offset += 0.6

        if(self.m_offset >(width/2)):
            self.m_offset = 0
        i = 5

        rect = QRectF(self.fsize,self.fsize,width - self.fsize*2, height - self.fsize * 2)
        while(i < width-5):
            waterY1 = A*math.sin(w*i +self.m_offset ) + k
            waterY2 = A*math.sin(w*i + self.m_offset + width/2*w) + k

            water1.lineTo(i, waterY1)
            water2.lineTo(i, waterY2)
            i += 1

        water1.lineTo(width-5,height)
        water2.lineTo(width-5,height)

        totalpath = QPainterPath()
        #totalpath.addRect(rect)
        #painter.setBrush(Qt.gray)
        painter.drawRect(self.rect())
        painter.save()
        totalpath.addEllipse(rect)
        totalpath.intersected(water1)
        painter.setPen(Qt.NoPen)

        #设置水波的透明度
        watercolor1 =QColor(self.bg_color)
        watercolor1.setAlpha(100)
        watercolor2 = QColor(self.bg_color)
        watercolor2.setAlpha(150)
        path = totalpath.intersected(water1)
        painter.setBrush(watercolor1)
        painter.drawPath(path)


        path = totalpath.intersected(water2)
        painter.setBrush(watercolor2)
        painter.drawPath(path)
        painter.restore()
        painter.end()
        #self.update()
    def update_percent(self, p):
        self.percent = p
        if self.m_waterOffset < 0.05:
            self.m_waterOffset += 0.001
        return p
class Progress(QDialog):
    percent = 0
    def __init__(self, text="",parent=None):
        super(Progress, self).__init__(parent)
        Font = QFont()
        Font.setFamily("Consolas")
        Font.setPointSize(12)
        self.setFont(Font)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.ProgressThread = ProgressThread()
        self.ProgressThread.signal.connect(self.percentUpdate)
        self.ProgressThread.start()
        width, height = 230, 230
        self.resize(width, height)
        self.water = WaterProgress((width, height), self)
        self.round = RoundProgress((width, height), self)
        self.label = QLabel(self)
        self.label.setText(QCoreApplication.translate("Dialog", text))
        print(self.label.width())
        self.label.move((width-self.label.width())/2, height/3*2)
        QMetaObject.connectSlotsByName(self)
        self.anim = Animation(self, )
    def connect(self, link):
        print(type(link))
        #self.setWindowFlags(Qt.WindowStaysOnTopHint) #置顶
        self.show()
    def percentUpdate(self):
        self.percent += 1
        self.water.update_percent(self.percent)
        self.water.paintEvent(None)
        self.round.update_percent(self.percent)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    r = Progress("<a link='b'>write something</a>")
    r.show()
    sys.exit(app.exec_())

做这个出来肯定是有用的啊, 看看我下次怎么为后续TCP server v2.0夯实基础咯!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • | 导入模块
  • | 效果
    • 1.线程内修改界面
      • 2. 窗口淡入(淡出)
        • 3.窗口去边框
          • 4.透明
            • 5.圆环进度条实现
              • 注意!!! ShareTechMomo不是本机字体(放上Consolas可以),自行下载!
            • 6.水波进度条(正弦函数)
              • 7.汇入Dialog
              • | 全部代码
                • 做这个出来肯定是有用的啊, 看看我下次怎么为后续TCP server v2.0夯实基础咯!
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档