IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python+PyQt5|文件传输测速和计算eta -> 正文阅读

[Python知识库]python+PyQt5|文件传输测速和计算eta


ETAESTIMATED ARRIVAL) 预计到达

  • 在pip中也有eta pip
image

计算公式 (v 为速度, sp 为当前进度,st 为总进度,t 为时间):
v = s p t v=\frac {s_p} {t} v=tsp??
p e r c e n t = s p s t ? 100 % percent = \frac {s_p} {s_t} · 100\% percent=st?sp???100%
e t a = s t ? s p v eta=\frac {s_t - s_p} {v} eta=vst??sp??
eta转换为 00:00:00 的形式,当速度为0和完成时,记为 --:--:--

效果展示

stylesheet (dialog, progressBar)采用渐变 .
dialog - run
dialog - wait
这是我原来做的:

import math
import os
import time

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import ImageLoader
from functions import convert


def PaintWater(self: QtWidgets.QWidget, painter, m_offset, m_waterOffset, percent, w_color):
    width, height = self.width(), self.height()
    percentage = 1 - percent / 100  # 水波走向:正弦函数 y = A(wx+l) + k
    w = 2 * math.pi / width  # w 表示 周期,值越大密度越大
    A = height * m_waterOffset  # A 表示振幅 ,理解为水波的上下振幅
    k = height * percentage  # k 表示 y 的偏移量,可理解为进度
    water1 = QtGui.QPainterPath()
    water2 = QtGui.QPainterPath()
    water1.moveTo(5, height)
    water2.moveTo(5, height)
    if m_offset > width / 2:
        m_offset = 0
    for i in range(5, width - 5):
        water1.lineTo(i, A * math.sin(w * i + m_offset) + k)
        water2.lineTo(i, A * math.sin(w * i + m_offset + width / 2 * w) + k)
        i += 1
    water1.lineTo(width - 5, height)
    water2.lineTo(width - 5, height)
    totalpath = QtGui.QPainterPath()
    totalpath.addRect(QtCore.QRectF(5, 5, width - 10, height - 10))
    painter.setBrush(QtCore.Qt.gray)
    painter.drawRect(self.rect())
    painter.save()
    painter.setPen(QtCore.Qt.NoPen)
    watercolor1 = QtGui.QColor(w_color)
    watercolor1.setAlpha(100)
    watercolor2 = QtGui.QColor(w_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()


class WaterProgressBar(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(WaterProgressBar, self).__init__(parent)
        self.resize(200, 60)
        # 背景填充灰色
        self.setAutoFillBackground(True)
        p = QtGui.QPalette()
        p.setColor(QtGui.QPalette.Background, QtCore.Qt.gray)
        self.setPalette(p)
        self.bg_color = QtGui.QColor("95BBFF")
        self.startTimer(80)
        self.m_waterOffset = 0.05
        self.m_offset = 50
        self.m_border_width = 10
        self._percent = 90
        self.finished = False
        self.__reversed = 100.

    def paintEvent(self, event):
        # 锯齿状绘画板;
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        width, height = self.width(), self.height()
        if not self.finished and self._percent == 100:
            self.finished = True

        if not self.finished:
            self.m_offset += 0.6
            PaintWater(self, painter, self.m_offset, self.m_waterOffset, self._percent, self.bg_color)
        elif self.__reversed > 0.:
            self.__reversed -= 3.1
            self.m_offset -= 0.6
            painter.setBrush(QtGui.QColor(self.bg_color))
            painter.drawRect(QtCore.QRectF(0, width / 100 * (100 - self.__reversed), width, height))
            PaintWater(self, painter, self.m_offset, self.m_waterOffset, self.__reversed, self.bg_color)
        else:
            super().paintEvent(event)

        m_font = QtGui.QFont()
        m_font.setFamily('Microsoft YaHei')
        m_font.setPixelSize(int(self.width() / 10))
        painter.setPen(QtCore.Qt.white)
        painter.setFont(m_font)
        painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "{}%".format(self._percent))
        painter.end()


class SimpleProgressDialog(QtWidgets.QDialog):

    def __init__(self, parent=None, total=100):
        super().__init__(parent)
        self._startTime = time.time()
        self._endTime = None

        self._startPos = None
        self._tracking = None
        self._endPos = None
        self.percent = 0
        self.progress = 0
        self.total = total
        self.setObjectName("FileProgress")
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.resize(480, 760)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        self.setFont(font)
        self.horizontalLayout = QtWidgets.QHBoxLayout(self)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.CentralLayoutWidget = QtWidgets.QWidget(self)
        self.CentralLayoutWidget.setStyleSheet("#CentralLayoutWidget {\n"
                                               "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
                                               "stop:0 rgba(82, 87, 250, 255), stop:1 rgba( "
                                               "245, 140, 107, 255));\n "
                                               "border-radius: 10px; border: 1px solid qlineargradient(spread:pad, "
                                               "x1:0, y1:0, x2:1, y2:1, stop:0 rgba(82, 87, 250, 255), stop:1 rgba("
                                               "245, 140, 107, 255));\n "
                                               "}")
        self.CentralLayoutWidget.setObjectName("CentralLayoutWidget")
        self.centralLayoutWidget = QtWidgets.QVBoxLayout(self.CentralLayoutWidget)
        self.centralLayoutWidget.setObjectName("centralLayoutWidget")
        self.closeButton = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.closeButton.setMaximumSize(QtCore.QSize(30, 30))
        self.closeButton.setBaseSize(QtCore.QSize(0, 0))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("images/close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.closeButton.setIcon(icon)
        self.closeButton.setIconSize(QtCore.QSize(24, 24))
        self.closeButton.setObjectName("closeButton")
        self.centralLayoutWidget.addWidget(self.closeButton, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.filename_label = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.filename_label.setStyleSheet("color: rgb(255, 255, 255);\n"
                                          "font: 11pt \"Consolas\";")
        self.filename_label.setScaledContents(False)
        self.filename_label.setObjectName("filename_label")
        self.centralLayoutWidget.addWidget(self.filename_label, 0, QtCore.Qt.AlignHCenter)
        self.icon_label = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.icon_label.setMaximumSize(QtCore.QSize(70, 70))
        self.icon_label.setScaledContents(True)
        self.icon_label.setObjectName("icon_label")
        self.centralLayoutWidget.addWidget(self.icon_label, 0, QtCore.Qt.AlignHCenter)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.centralLayoutWidget.addItem(spacerItem)
        self.fileLayout = QtWidgets.QHBoxLayout()
        self.fileLayout.setObjectName("fileLayout")
        self.size_label_tag = QtWidgets.QLabel()
        self.size_label_tag.setObjectName("size_label")
        self.size_label_tag.setStyleSheet("color: rgb(255, 255, 255);\n"
                                          "font: 11pt \"Consolas\";")
        self.fileLayout.addWidget(self.size_label_tag)
        self.size_label = QtWidgets.QLabel()
        self.size_label.setStyleSheet("color: rgb(255, 255, 0);\n"
                                      "font: 11pt \"Consolas\";")
        self.fileLayout.addWidget(self.size_label)
        widget = QtWidgets.QWidget()
        widget.setLayout(self.fileLayout)
        self.centralLayoutWidget.addWidget(widget, 0, QtCore.Qt.AlignHCenter)
        self.line = QtWidgets.QFrame(self.CentralLayoutWidget)
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.centralLayoutWidget.addWidget(self.line)
        self.infoLayout = QtWidgets.QHBoxLayout()
        self.infoLayout.setObjectName("infoLayout")
        self.progressLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.progressLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                                         "color: rgb(83, 230, 60);")
        self.progressLabel.setObjectName("progress")
        self.infoLayout.addWidget(self.progressLabel)
        self.speedLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.speedLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                                      "color: rgb(255, 255, 0);")
        self.speedLabel.setObjectName("speed")
        self.infoLayout.addWidget(self.speedLabel)
        self.eta = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.eta.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                               "color: rgb(11, 235, 255);")
        self.eta.setObjectName("eta")
        self.infoLayout.addWidget(self.eta)
        self.centralLayoutWidget.addLayout(self.infoLayout)
        self.progressbar = QtWidgets.QProgressBar(self.CentralLayoutWidget)
        self.progressbar.setMinimum(0)
        self.progressbar.setProperty("value", 0)
        self.progressbar.setTextVisible(False)
        self.progressbar.setInvertedAppearance(False)
        self.progressbar.setObjectName("progressbar")
        self.centralLayoutWidget.addWidget(self.progressbar)
        self.percentLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.percentLabel.setStyleSheet("font: 11pt \"Consolas\";\n"
                                        "color: rgb(0, 85, 255);")
        self.percentLabel.setObjectName("percent")
        self.centralLayoutWidget.addWidget(self.percentLabel, 0, QtCore.Qt.AlignHCenter)
        self.openFile = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.openFile.setMaximumSize(QtCore.QSize(100, 16777215))
        self.openFile.setObjectName("openFile")
        self.centralLayoutWidget.addWidget(self.openFile, 0, QtCore.Qt.AlignHCenter)
        self.openPath = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.openPath.setMaximumSize(QtCore.QSize(100, 16777215))
        self.openPath.setObjectName("openFile_2")
        self.centralLayoutWidget.addWidget(self.openPath, 0, QtCore.Qt.AlignHCenter)
        self.horizontalLayout.addWidget(self.CentralLayoutWidget)

        self.closeButton.clicked.connect(self.close)
        QtCore.QMetaObject.connectSlotsByName(self)

        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("FileProgress", "Dialog"))
        self.filename_label.setText(_translate("FileProgress", "{filename}"))
        self.progressLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>当前进度</p></body></html>"))
        self.progressLabel.setText(_translate("FileProgress", f"0 / {convert(self.total)}"))
        self.speedLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>速度</p></body></html>"))
        self.speedLabel.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
        self.speedLabel.setText(_translate("FileProgress", "speed"))
        self.eta.setToolTip(_translate("FileProgress",
                                       "<html><head/><body><p><span style=\" font-weight:600; "
                                       "color:#ff0000;\">eta</span><span style=\" color:#000000;\">, 即</span><span "
                                       "style=\" font-weight:600; color:#000000;\">E</span><span style=\" "
                                       "color:#000000;\">stimated </span><span style=\" font-weight:600; "
                                       "color:#000000;\">T</span><span style=\" color:#000000;\">ime of </span><span "
                                       "style=\" font-weight:600; color:#000000;\">A</span><span style=\" "
                                       "color:#000000;\">rrival, </span><span style=\" font-weight:600; "
                                       "color:#000000;\">预计到达时间</span><span style=\" "
                                       "color:#000000;\">.</span></p></body></html>"))
        self.eta.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
        self.eta.setText(_translate("FileProgress", "eta"))
        self.percentLabel.setText(_translate("FileProgress", "0%"))
        self.openFile.setText(_translate("FileProgress", "打开文件"))
        self.openPath.setText(_translate("FileProgress", "转到目录"))
        self.size_label_tag.setText(_translate("FileProgress", "大小:"))
        self.size_label.setText(_translate("FileProgress", f"{convert(self.total)}"))
        self.progressbar.setRange(0, 0)
        self.setWindowOpacity(0.9)
        self.progressbar.setStyleSheet("\n"
                                       "#progressbar {\n"
                                       "    min-height: 12px;\n"
                                       "    max-height: 12px;\n"
                                       "    border-radius: 6px;\n"
                                       "}\n"
                                       "#progressbar::chunk {\n"
                                       "    border-radius: 6px;\n"
                                       "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
                                       f"stop:0 rgba(50, 0, 255, 255), stop:1 rgba({self.percent}, 185, 255, 255));\n "
                                       "}")
        self.openFile.setEnabled(False)

    def _set_eta(self, _stamp: (int, float)):
        if self.is_finished():
            if not isinstance(self._endTime, (int, float)):
                self._endTime = time.time()
            self.eta.setText("total " + str(time.strftime("%H:%M:%S",
                                                          time.gmtime(float(self._endTime - self._startTime)))))
        else:
            if _stamp == 0:
                self.eta.setText("eta --:--:--")
            else:
                self.eta.setText("eta " + str(time.strftime("%H:%M:%S", time.gmtime(float(_stamp)))))

    def _set_speed(self, _transfer: int):
        self.speedLabel.setText(f"{'total ' if self.is_finished() else str()}{convert(_transfer)}/s")

    def _set_progress(self):
        if self.is_finished():
            self.progressLabel.setText("finished")
        else:
            self.progressLabel.setText(f"{convert(self.progress)} / {convert(self.total)}")

    def mouseMoveEvent(self, e):  # re-write mouseMoveEvent
        if self._tracking:
            self._endPos = e.pos() - self._startPos
            self.move(self.pos() + self._endPos)

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._startPos = QtCore.QPoint(e.x(), e.y())
            self._tracking = True

    def mouseReleaseEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._tracking = False
            self._startPos = None
            self._endPos = None

    @QtCore.pyqtSlot(int)
    def updateValue(self, length=1):
        self.progress += length
        if self.progress > self.total:
            self.progress = self.total
        self.percent = int(round(self.progress / self.total, 2) * 100)
        if self.is_finished():
            self.openFile.setEnabled(True)
            self.progressbar.hide()
            self.percentLabel.hide()
        self.progressbar.setMaximum(100)
        self.progressbar.setValue(self.percent)
        self.percentLabel.setText(f"{self.percent}%")
        self.valueChangedEvent(length)
        self._set_progress()

    def is_finished(self) -> bool:
        return self.progress == self.total

    def valueChangedEvent(self, added):
        pass


class ProgressDialog(SimpleProgressDialog):
    def __init__(self, total, filename, filepath, time_stamp=None, progress=None, parent=None, x=0, y=0):
        super(ProgressDialog, self).__init__(parent, total=total)
        self.resize(320, 640)
        self.timeStamp = time.time()
        self.eta_value = 0
        self.speed = 0
        self.filename = filename
        self.filepath = filepath
        self.file = os.path.join(filepath, filename)
        self.eta_added_value = 0
        self.icon_label.setPixmap(QtGui.QPixmap(ImageLoader.get(filename)))
        self.filename_label.setText(filename)

        self.openFile.clicked.connect(self.startFile)
        self.openPath.clicked.connect(self.startPath)

        self.count_eta_timer = QtCore.QTimer(self)
        self.count_eta_timer.timeout.connect(self.update)
        self.count_eta_timer.start(500)
        self.update()

        if isinstance(progress, int) and isinstance(progress, (int, float)):
            self.already_start(progress, time_stamp)
            self.exec_()

    def already_start(self, progress: int, time_stamp: (int, float)):
        self.progress = progress
        self._startTime = time_stamp

    def valueChangedEvent(self, added):
        self.eta_added_value += added

    def startFile(self, *args):
        if os.path.isfile(self.file):
            os.startfile(self.file)

    def startPath(self, *args):
        if os.path.isfile(self.filepath):
            os.startfile(self.filepath)

    def update(self, *args):
        super().update(*args)
        self._set_eta(self.eta_value)
        self._set_speed(self.speed)
        if not self.is_finished():
            self.speed = self.eta_added_value / (
                    time.time() - self.timeStamp) if time.time() - self.timeStamp != 0 else 0
            self.eta_value = (self.total - self.progress) / self.speed if self.speed != 0 else 0
            self.timeStamp = time.time()
        else:
            self.speed = self.total / (self._endTime - self._startTime)
        self.eta_added_value = 0


class FileListWidget(QtWidgets.QListWidget):
    class ListWidgetLayout(QtWidgets.QWidget):
        def __init__(self, name, total, size, parent=None):
            super(FileListWidget.ListWidgetLayout, self).__init__(parent)
            self.size = size
            self.total = total
            self.segment = math.ceil(self.size // self.total)
            self.progress = 0

            hbox = QtWidgets.QHBoxLayout(self)
            vbox = QtWidgets.QVBoxLayout()
            vbox.addWidget(QtWidgets.QLabel(name + f"\n({convert(self.size)})", self))
            progress = QtWidgets.QProgressBar()
            progress.setMaximum(total)
            progress.setStyleSheet("QProgressBar{\n"
                                   "text-align: center;\n"
                                   'font: 9pt "Consolas";\n'
                                   "}")
            vbox.setObjectName("name, speed Info")
            hbox.setObjectName("Info and Progress")
            progress.setTextVisible(True)
            progress.setRange(0, 0)
            self.label = QtWidgets.QLabel(self)
            self.label.setStyleSheet("color: rgb(60, 112, 255);")
            vbox.addWidget(self.label)
            self.progressbar = progress
            vbox.setSpacing(2)
            hbox.addLayout(vbox)
            hbox.addWidget(progress)
            self.setLayout(hbox)

            fonts = QtGui.QFont()
            fonts.setFamily("Consolas")
            fonts.setPointSize(9)
            self.setFont(fonts)
            self.label.setFont(fonts)
            self.start_time = time.time()

            self.timer = QtCore.QTimer(self)
            self.timer.timeout.connect(self.timers)
            self.timer.start(50)

        def timers(self, *args) -> None:
            timeit = self.get_time()
            if timeit == 0:
                return  # ZeroDivisionError: integer division or modulo by zero
            content = f"{convert(int((self.segment * self.progress) / timeit))}/s ({self.str_time()} 秒)"
            self.label.setText(content)

        def get_progressbar(self) -> QtWidgets.QProgressBar:
            return self.progressbar

        def is_finished(self) -> bool:
            return bool(self.progress >= self.total)

        def update(self) -> None:
            if self.progress == 0:
                self.progressbar.setMaximum(self.total)
            if self.is_finished():
                return
            self.progress += 1
            if self.is_finished():
                self.end_time = time.time()
            self.progressbar.setValue(self.progress)

        def get_total(self) -> int:
            return self.total

        def get_time(self) -> float:
            return getattr(self, "end_time", time.time()) - self.start_time

        def str_time(self) -> str:
            return "%0.1f" % (self.get_time())

        def get_progress(self) -> int:
            return self.progress

    class ListItem(QtWidgets.QListWidgetItem):
        def __init__(self, parent: QtWidgets.QListWidget, icon: QtGui.QIcon, index: int, layout, size=(200, 80)):
            super(FileListWidget.ListItem, self).__init__(icon, str(), parent)
            self.index_name = index
            self.setSizeHint(QtCore.QSize(200, 80))
            self.setSizeHint(QtCore.QSize(*size))
            parent.addItem(self)
            parent.setItemWidget(self, layout)

    DOWNLOAD = 0
    UPLOAD = 1

    def __init__(self, _save_path, parent=None):
        self.x, self.y = 0, 0
        self.dialog_index = 0
        self.dialog = None
        self.rightClickedItem = None
        self.path = None
        self.fpath = None
        self.current = ""
        super().__init__(parent)
        self.setWindowIcon(QtGui.QIcon("images/file.png"))
        self.download = QtGui.QIcon("images/download.png")
        self.upload = QtGui.QIcon("images/upload.png")
        self.LOAD_dict = {self.DOWNLOAD: self.download,
                          self.UPLOAD: self.upload}
        self.save_path = _save_path
        self.filedict = {}
        self.pathdict = {}
        self.namedict = {}
        self.infodict = {}
        self.setObjectName("FileDisplayWindow")
        self.resize(666, 421)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        self.setFont(font)

        self.setWindowTitle(QtCore.QCoreApplication.translate("Dialog", "Files"))

        self.itemClicked.connect(self.fileClicked)

        self.menu = QtWidgets.QMenu(self)
        open_file = QtWidgets.QAction(QtGui.QIcon("images/file.png"), '打开文件', self)
        open_file.triggered.connect(self.startfile)
        self.menu.addAction(open_file)
        open_path = QtWidgets.QAction(QtGui.QIcon("images/folder.png"), '打开文件夹', self)
        open_path.triggered.connect(self.startpath)
        self.menu.addAction(open_path)

        QtCore.QMetaObject.connectSlotsByName(self)

    def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
        super().mousePressEvent(event)
        if event.button() == QtCore.Qt.RightButton and self.itemAt(event.pos()):
            item = self.itemAt(event.pos())
            index: int = item.index_name
            self.fpath = self.pathdict[index]
            self.path = os.path.dirname(self.fpath)
            self.menu.exec(event.globalPos())

    @QtCore.pyqtSlot(str, int, int, tuple)
    def new_file(self, name, total, size, info):
        self.activateWindow()  # 窗口置顶

        index = len(self.filedict)
        _type, localfile = info
        layout = FileListWidget.ListWidgetLayout(name, total, size)
        self.filedict[index] = (layout, size)
        self.pathdict[index] = localfile
        self.infodict[index] = (total, name, os.path.dirname(localfile), time.time())
        item = FileListWidget.ListItem(self, self.LOAD_dict.get(_type, self.UPLOAD), index, layout)
        self.show()

    @QtCore.pyqtSlot(int)
    def update_file(self, index: int):
        layout, size = self.filedict[index]
        layout: FileListWidget.ListWidgetLayout
        layout.update()
        if isinstance(self.dialog, ProgressDialog):
            if index == self.dialog_index:
                self.dialog.updateValue(1)

    def fileClicked(self, item: ListItem):
        index = item.index_name
        self.dialog = ProgressDialog(*self.infodict[index], self.filedict[index][0].get_progress())
        self.dialog_index = index

    def startfile(self, *args):
        if isinstance(self.fpath, str) and os.path.isfile(self.fpath):
            os.startfile(self.fpath)

    def startpath(self, *args):
        if isinstance(self.path, str) and os.path.isdir(self.path):
            os.startfile(self.path)

    def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
        super(FileListWidget, self).mouseMoveEvent(event)
        self.x, self.y = event.x(), event.y()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    a = FileListWidget(os.path.join(os.path.dirname(os.path.realpath(__file__)), "database", "resource"))
    a.new_file("asdf", 1010, 11111, (0, "C:/users/zhnwe/desktop/1.rte"))
    a.show()
    app.exec_()

现在呢,我有创建了一个类_cSpeed, 方便在3个类中管理.

class _cSpeed(object):
    def __init__(self, total: (int, float) = 100, slot: (QtCore.pyqtSlot, None) = None):
        self.__create_time = time.time()
        self.__end_time = None
        self.__update_value = int()
        self.__total_value = total
        self.slots = []
        self.add_slot(slot)

        self.timed_once = time.time()
        self.update_once = int()

    def add_slot(self, slot: QtCore.pyqtSlot):
        if callable(slot):
            self.slots.append(slot)

    def get_total(self) -> str:
        return convert(self.__total_value)

    def _count_speed(self) -> float:  # once
        resp = self.update_once / (time.time() - self.timed_once) if (time.time() - self.timed_once) else 0.
        self.update_once = int()
        self.timed_once = time.time()
        return resp
        #  return (self.__update_value / self._get_time()) if self._get_time() else 0.

    def _round_speed(self, value: int = 2) -> float:
        return round(self._count_speed(), value)

    def get_speed(self, value: int = 2, exact=False) -> str:
        return f"{convert(self._round_speed(value), bool(exact))}/s"

    def get_percent(self) -> int:
        return int(round(self.__update_value / self.__total_value, 2) * 100)

    def update_value(self, value: (int, float) = 1.) -> None:
        self.__update_value += value
        self.update_once += value
        if self.__update_value >= self.__total_value:
            self.__update_value = self.__total_value
            if self.__end_time is None:
                self.__end_time = time.time()
        for slot in self.slots:
            slot()

    def _value(self) -> (float, int):
        return self.__update_value

    def is_finished(self) -> bool:
        return not bool(self._get_over())

    def get_progress(self) -> str:
        return f"{convert(self.__update_value)} / {convert(self.__total_value)}" \
            if self._get_over() else convert(self.__total_value)

    def _get_over(self) -> float:
        return self.__total_value - self.__update_value

    def get_eta(self) -> str:
        assert isinstance(self.__total_value, (int, float)), "total value is Incalculable!"
        return f'eta {time.strftime("%H:%M:%S", time.gmtime(self._get_over() / self._count_speed())) if self._count_speed() else "--:--:--"}' \
            if self._get_over() else \
            f'total {time.strftime("%H:%M:%S", time.gmtime(self.__end_time - self.__create_time))}'

    def _get_time(self) -> float:
        return (self.__end_time if isinstance(self.__end_time, float) else time.time()) - self.__create_time

全部代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'progressbar.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

import math
import os
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import ImageLoader
from functions import convert


class _cSpeed(object):
    def __init__(self, total: (int, float) = 100, slot: (QtCore.pyqtSlot, None) = None):
        self.__create_time = time.time()
        self.__end_time = None
        self.__update_value = int()
        self.__total_value = total
        self.slots = []
        self.add_slot(slot)

        self.timed_once = time.time()
        self.update_once = int()

    def add_slot(self, slot: QtCore.pyqtSlot):
        if callable(slot):
            self.slots.append(slot)

    def get_total(self) -> str:
        return convert(self.__total_value)

    def _count_speed(self) -> float:  # once
        resp = self.update_once / (time.time() - self.timed_once) if (time.time() - self.timed_once) else 0.
        self.update_once = int()
        self.timed_once = time.time()
        return resp
        #  return (self.__update_value / self._get_time()) if self._get_time() else 0.

    def _round_speed(self, value: int = 2) -> float:
        return round(self._count_speed(), value)

    def get_speed(self, value: int = 2, exact=False) -> str:
        return f"{convert(self._round_speed(value), bool(exact))}/s"

    def get_percent(self) -> int:
        return int(round(self.__update_value / self.__total_value, 2) * 100)

    def update_value(self, value: (int, float) = 1.) -> None:
        self.__update_value += value
        self.update_once += value
        if self.__update_value >= self.__total_value:
            self.__update_value = self.__total_value
            if self.__end_time is None:
                self.__end_time = time.time()
        for slot in self.slots:
            slot()

    def _value(self) -> (float, int):
        return self.__update_value

    def is_finished(self) -> bool:
        return not bool(self._get_over())

    def get_progress(self) -> str:
        return f"{convert(self.__update_value)} / {convert(self.__total_value)}" \
            if self._get_over() else convert(self.__total_value)

    def _get_over(self) -> float:
        return self.__total_value - self.__update_value

    def get_eta(self) -> str:
        assert isinstance(self.__total_value, (int, float)), "total value is Incalculable!"
        return f'eta {time.strftime("%H:%M:%S", time.gmtime(self._get_over() / self._count_speed())) if self._count_speed() else "--:--:--"}' \
            if self._get_over() else \
            f'total {time.strftime("%H:%M:%S", time.gmtime(self.__end_time - self.__create_time))}'

    def _get_time(self) -> float:
        return (self.__end_time if isinstance(self.__end_time, float) else time.time()) - self.__create_time


class WaterProgressBar(QtWidgets.QWidget):
    def PaintWater(self: QtWidgets.QWidget, painter, m_offset, m_waterOffset, percent, w_color):
        width, height = self.width(), self.height()
        percentage = 1 - percent / 100  # 水波走向:正弦函数 y = A(wx+l) + k
        w = 2 * math.pi / width  # w 表示 周期,值越大密度越大
        A = height * m_waterOffset  # A 表示振幅 ,理解为水波的上下振幅
        k = height * percentage  # k 表示 y 的偏移量,可理解为进度
        water1 = QtGui.QPainterPath()
        water2 = QtGui.QPainterPath()
        water1.moveTo(5, height)
        water2.moveTo(5, height)
        if m_offset > width / 2:
            m_offset = 0
        for i in range(5, width - 5):
            water1.lineTo(i, A * math.sin(w * i + m_offset) + k)
            water2.lineTo(i, A * math.sin(w * i + m_offset + width / 2 * w) + k)
            i += 1
        water1.lineTo(width - 5, height)
        water2.lineTo(width - 5, height)
        total_path = QtGui.QPainterPath()
        total_path.addRect(QtCore.QRectF(5, 5, width - 10, height - 10))
        painter.setBrush(QtCore.Qt.gray)
        painter.drawRect(self.rect())
        painter.save()
        painter.setPen(QtCore.Qt.NoPen)
        watercolor1 = QtGui.QColor(w_color)
        watercolor1.setAlpha(100)
        watercolor2 = QtGui.QColor(w_color)
        watercolor2.setAlpha(150)
        path = total_path.intersected(water1)
        painter.setBrush(watercolor1)
        painter.drawPath(path)
        path = total_path.intersected(water2)
        painter.setBrush(watercolor2)
        painter.drawPath(path)
        painter.restore()

    def __init__(self, parent=None):
        super(WaterProgressBar, self).__init__(parent)
        self.resize(200, 60)
        # 背景填充灰色
        self.setAutoFillBackground(True)
        p = QtGui.QPalette()
        p.setColor(QtGui.QPalette.Background, QtCore.Qt.gray)
        self.setPalette(p)
        self.bg_color = QtGui.QColor("95BBFF")
        self.startTimer(80)
        self.m_waterOffset = 0.05
        self.m_offset = 50
        self.m_border_width = 10
        self._percent = 90
        self.finished = False
        self.__reversed = 100.

    def paintEvent(self, event):
        # 锯齿状绘画板;
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        width, height = self.width(), self.height()
        if not self.finished and self._percent == 100:
            self.finished = True

        if not self.finished:
            self.m_offset += 0.6
            self.PaintWater(self, painter, self.m_offset, self.m_waterOffset, self._percent, self.bg_color)
        elif self.__reversed > 0.:
            self.__reversed -= 3.1
            self.m_offset -= 0.6
            painter.setBrush(QtGui.QColor(self.bg_color))
            painter.drawRect(QtCore.QRectF(0, width / 100 * (100 - self.__reversed), width, height))
            self.PaintWater(self, painter, self.m_offset, self.m_waterOffset, self.__reversed, self.bg_color)
        else:
            super().paintEvent(event)

        m_font = QtGui.QFont()
        m_font.setFamily('Microsoft YaHei')
        m_font.setPixelSize(int(self.width() / 10))
        painter.setPen(QtCore.Qt.white)
        painter.setFont(m_font)
        painter.drawText(self.rect(), QtCore.Qt.AlignCenter, "{}%".format(self._percent))
        painter.end()


class SimpleProgressDialog(QtWidgets.QDialog):

    def __init__(self, parent=None, cSpeed: _cSpeed = _cSpeed(100)):
        super().__init__(parent)

        self._startPos = None
        self._tracking = None
        self._endPos = None

        self.percent = 0
        self._cSpeed = cSpeed
        self.setObjectName("FileProgress")
        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去边框
        self.resize(480, 760)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        self.setFont(font)
        self.horizontalLayout = QtWidgets.QHBoxLayout(self)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.CentralLayoutWidget = QtWidgets.QWidget(self)
        self.CentralLayoutWidget.setStyleSheet("#CentralLayoutWidget {\n"
                                               "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
                                               "stop:0 rgba(82, 87, 250, 255), stop:1 rgba( "
                                               "245, 140, 107, 255));\n "
                                               "border-radius: 10px; border: 1px solid qlineargradient(spread:pad, "
                                               "x1:0, y1:0, x2:1, y2:1, stop:0 rgba(82, 87, 250, 255), stop:1 rgba("
                                               "245, 140, 107, 255));\n "
                                               "}")
        self.CentralLayoutWidget.setObjectName("CentralLayoutWidget")
        self.centralLayoutWidget = QtWidgets.QVBoxLayout(self.CentralLayoutWidget)
        self.centralLayoutWidget.setObjectName("centralLayoutWidget")
        self.closeButton = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.closeButton.setMaximumSize(QtCore.QSize(30, 30))
        self.closeButton.setBaseSize(QtCore.QSize(0, 0))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("images/close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.closeButton.setIcon(icon)
        self.closeButton.setIconSize(QtCore.QSize(24, 24))
        self.closeButton.setObjectName("closeButton")
        self.centralLayoutWidget.addWidget(self.closeButton, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.filename_label = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.filename_label.setStyleSheet("color: rgb(255, 255, 255);\n"
                                          "font: 11pt \"Consolas\";")
        self.filename_label.setScaledContents(False)
        self.filename_label.setObjectName("filename_label")
        self.centralLayoutWidget.addWidget(self.filename_label, 0, QtCore.Qt.AlignHCenter)
        self.icon_label = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.icon_label.setMaximumSize(QtCore.QSize(70, 70))
        self.icon_label.setScaledContents(True)
        self.icon_label.setObjectName("icon_label")
        self.centralLayoutWidget.addWidget(self.icon_label, 0, QtCore.Qt.AlignHCenter)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.centralLayoutWidget.addItem(spacerItem)
        self.fileLayout = QtWidgets.QHBoxLayout()
        self.fileLayout.setObjectName("fileLayout")
        self.size_label_tag = QtWidgets.QLabel()
        self.size_label_tag.setObjectName("size_label")
        self.size_label_tag.setStyleSheet("color: rgb(255, 255, 255);\n"
                                          "font: 11pt \"Consolas\";")
        self.fileLayout.addWidget(self.size_label_tag)
        self.size_label = QtWidgets.QLabel()
        self.size_label.setStyleSheet("color: rgb(255, 255, 0);\n"
                                      "font: 11pt \"Consolas\";")
        self.fileLayout.addWidget(self.size_label)
        widget = QtWidgets.QWidget()
        widget.setLayout(self.fileLayout)
        self.centralLayoutWidget.addWidget(widget, 0, QtCore.Qt.AlignHCenter)
        self.line = QtWidgets.QFrame(self.CentralLayoutWidget)
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.centralLayoutWidget.addWidget(self.line)
        self.infoLayout = QtWidgets.QHBoxLayout()
        self.infoLayout.setObjectName("infoLayout")
        self.progressLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.progressLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                                         "color: rgb(83, 230, 60);")
        self.progressLabel.setObjectName("progress")
        self.infoLayout.addWidget(self.progressLabel)
        self.speedLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.speedLabel.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                                      "color: rgb(255, 255, 0);")
        self.speedLabel.setObjectName("speed")
        self.infoLayout.addWidget(self.speedLabel)
        self.eta = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.eta.setStyleSheet("font: 11pt \"Comic Sans MS\";\n"
                               "color: rgb(11, 235, 255);")
        self.eta.setObjectName("eta")
        self.infoLayout.addWidget(self.eta)
        self.centralLayoutWidget.addLayout(self.infoLayout)
        self.progressbar = QtWidgets.QProgressBar(self.CentralLayoutWidget)
        self.progressbar.setMinimum(0)
        self.progressbar.setProperty("value", 0)
        self.progressbar.setTextVisible(False)
        self.progressbar.setInvertedAppearance(False)
        self.progressbar.setObjectName("progressbar")
        self.centralLayoutWidget.addWidget(self.progressbar)
        self.percentLabel = QtWidgets.QLabel(self.CentralLayoutWidget)
        self.percentLabel.setStyleSheet("font: 11pt \"Consolas\";\n"
                                        "color: rgb(0, 85, 255);")
        self.percentLabel.setObjectName("percent")
        self.centralLayoutWidget.addWidget(self.percentLabel, 0, QtCore.Qt.AlignHCenter)
        self.openFile = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.openFile.setMaximumSize(QtCore.QSize(100, 16777215))
        self.openFile.setObjectName("openFile")
        self.centralLayoutWidget.addWidget(self.openFile, 0, QtCore.Qt.AlignHCenter)
        self.openPath = QtWidgets.QPushButton(self.CentralLayoutWidget)
        self.openPath.setMaximumSize(QtCore.QSize(100, 16777215))
        self.openPath.setObjectName("openFile_2")
        self.centralLayoutWidget.addWidget(self.openPath, 0, QtCore.Qt.AlignHCenter)
        self.horizontalLayout.addWidget(self.CentralLayoutWidget)

        self.closeButton.clicked.connect(self.close)
        QtCore.QMetaObject.connectSlotsByName(self)

        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("FileProgress", "Dialog"))
        self.filename_label.setText(_translate("FileProgress", "{filename}"))
        self.progressLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>当前进度</p></body></html>"))
        self.progressLabel.setText(_translate("FileProgress", f") / {self._cSpeed.get_total()}"))
        self.speedLabel.setToolTip(_translate("FileProgress", "<html><head/><body><p>速度</p></body></html>"))
        self.speedLabel.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
        self.speedLabel.setText(_translate("FileProgress", "speed"))
        self.eta.setToolTip(_translate("FileProgress",
                                       "<html><head/><body><p><span style=\" font-weight:600; "
                                       "color:#ff0000;\">eta</span><span style=\" color:#000000;\">, 即</span><span "
                                       "style=\" font-weight:600; color:#000000;\">E</span><span style=\" "
                                       "color:#000000;\">stimated </span><span style=\" font-weight:600; "
                                       "color:#000000;\">T</span><span style=\" color:#000000;\">ime of </span><span "
                                       "style=\" font-weight:600; color:#000000;\">A</span><span style=\" "
                                       "color:#000000;\">rrival, </span><span style=\" font-weight:600; "
                                       "color:#000000;\">预计到达时间</span><span style=\" "
                                       "color:#000000;\">.</span></p></body></html>"))
        self.eta.setWhatsThis(_translate("FileProgress", "<html><head/><body><p><br/></p></body></html>"))
        self.eta.setText(_translate("FileProgress", "eta"))
        self.percentLabel.setText(_translate("FileProgress", "0%"))
        self.openFile.setText(_translate("FileProgress", "打开文件"))
        self.openPath.setText(_translate("FileProgress", "转到目录"))
        self.size_label_tag.setText(_translate("FileProgress", "大小:"))
        self.size_label.setText(_translate("FileProgress", self._cSpeed.get_total()))
        self.progressbar.setRange(0, 0)
        self.setWindowOpacity(0.9)
        self.progressbar.setStyleSheet("\n"
                                       "#progressbar {\n"
                                       "    min-height: 12px;\n"
                                       "    max-height: 12px;\n"
                                       "    border-radius: 6px;\n"
                                       "}\n"
                                       "#progressbar::chunk {\n"
                                       "    border-radius: 6px;\n"
                                       "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, "
                                       f"stop:0 rgba(50, 0, 255, 255), stop:1 rgba({self._cSpeed.get_percent()}, 185, "
                                       f"255, 255));\n "
                                       "}")
        self.openFile.setEnabled(False)
        self._cSpeed.add_slot(self.updateValue)

    def _set_eta(self):
        """
        def _set_eta(self, _stamp: (int, float)):
            if self.is_finished():
                if not isinstance(self._endTime, (int, float)):
                    self._endTime = time.time()
                self.eta.setText("total " + str(time.strftime("%H:%M:%S",
                                                              time.gmtime(float(self._endTime - self._startTime)))))
            else:
                if _stamp == 0:
                    self.eta.setText("eta --:--:--")
                else:
                    self.eta.setText("eta " + str(time.strftime("%H:%M:%S", time.gmtime(float(_stamp)))))
                    """
        self.eta.setText(self._cSpeed.get_eta())

    def _set_speed(self):
        """
        def _set_speed(self, _transfer: int):
            self.speedLabel.setText(f"{'total ' if self.is_finished() else str()}{convert(_transfer)}/s")
            """
        self.speedLabel.setText(self._cSpeed.get_speed())

    def _set_progress(self):
        """
        def _set_progress(self):
            if self.is_finished():
                self.progressLabel.setText("finished")
            else:
                self.progressLabel.setText(f"{convert(self.progress)} / {convert(self.total)}")
                """
        self.progressLabel.setText(self._cSpeed.get_progress())

    def mouseMoveEvent(self, e):  # re-write mouseMoveEvent
        if self._tracking:
            self._endPos = e.pos() - self._startPos
            self.move(self.pos() + self._endPos)

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._startPos = QtCore.QPoint(e.x(), e.y())
            self._tracking = True

    def mouseReleaseEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._tracking = False
            self._startPos = None
            self._endPos = None

    @QtCore.pyqtSlot()
    def updateValue(self):
        self.percent = self._cSpeed.get_percent()
        if self._cSpeed.is_finished():
            self.openFile.setEnabled(True)
            self.progressbar.hide()
            self.percentLabel.hide()
        if self._cSpeed.get_percent() > 0:
            self.progressbar.setMaximum(100)
            self.progressbar.setValue(self.percent)
        self.percentLabel.setText(f"{self.percent}%")

        self._set_speed()
        self._set_eta()
        self._set_progress()


class ProgressDialog(SimpleProgressDialog):
    def __init__(self, _cSpeed, filename, filepath, parent=None):
        super(ProgressDialog, self).__init__(parent, cSpeed=_cSpeed)
        self.resize(320, 640)
        self.filename = filename
        self.filepath = filepath
        self.file = os.path.join(filepath, filename)
        self.icon_label.setPixmap(QtGui.QPixmap(ImageLoader.get(filename)))
        self.filename_label.setText(filename)

        self.openFile.clicked.connect(self.startFile)
        self.openPath.clicked.connect(self.startPath)
        self.updateValue()
        self.startTimer(500)

        self.exec_()

    def startFile(self, *args):
        if os.path.isfile(self.file):
            os.startfile(self.file)

    def timerEvent(self, a0: QtCore.QTimerEvent) -> None:
        self.updateValue()

    def startPath(self, *args):
        if os.path.isfile(self.filepath):
            os.startfile(self.filepath)


class FileListWidget(QtWidgets.QListWidget):
    class ListWidgetLayout(QtWidgets.QWidget):
        def __init__(self, name, cSpeed: _cSpeed = _cSpeed(100), parent=None):
            super(FileListWidget.ListWidgetLayout, self).__init__(parent)
            self._cSpeed = cSpeed

            hbox = QtWidgets.QHBoxLayout(self)
            vbox = QtWidgets.QVBoxLayout()
            vbox.addWidget(QtWidgets.QLabel(name + f"\n({self._cSpeed.get_total()})", self))
            progress = QtWidgets.QProgressBar()
            progress.setMaximum(100)
            progress.setStyleSheet("QProgressBar{\n"
                                   "text-align: center;\n"
                                   'font: 9pt "Consolas";\n'
                                   "}")
            vbox.setObjectName("name, speed Info")
            hbox.setObjectName("Info and Progress")
            progress.setTextVisible(True)
            progress.setRange(0, 0)
            self.eta_label = QtWidgets.QLabel(self)
            self.eta_label.setStyleSheet("color: rgb(60, 112, 255);")
            vbox.addWidget(self.eta_label)
            self.progressbar = progress
            vbox.setSpacing(2)
            hbox.addLayout(vbox)
            hbox.addWidget(progress)
            self.setLayout(hbox)

            fonts = QtGui.QFont()
            fonts.setFamily("Consolas")
            fonts.setPointSize(9)
            self.setFont(fonts)
            self.eta_label.setFont(fonts)
            self.start_time = time.time()

            self._cSpeed.add_slot(self.updateValue)

            self.startTimer(100)

        def timerEvent(self, a0: QtCore.QTimerEvent) -> None:
            self.eta_label.setText(f"{self._cSpeed.get_speed()} ({self._cSpeed.get_eta()})")

        @QtCore.pyqtSlot()
        def updateValue(self) -> None:
            if self._cSpeed.get_percent() > 0:
                self.progressbar.setMaximum(100)
                self.progressbar.setValue(self._cSpeed.get_percent())

    class ListItem(QtWidgets.QListWidgetItem):
        def __init__(self, parent: QtWidgets.QListWidget, icon: QtGui.QIcon, index: int, layout, size=(200, 100)):
            super(FileListWidget.ListItem, self).__init__(icon, str(), parent)
            self.index_name = index
            self.setSizeHint(QtCore.QSize(*size))
            self.setSizeHint(QtCore.QSize(*size))
            parent.addItem(self)
            parent.setItemWidget(self, layout)

    DOWNLOAD = 0
    UPLOAD = 1

    def __init__(self, _save_path, parent=None):
        self.x, self.y = 0, 0
        self.dialog_index = 0
        self.dialog = None
        self.rightClickedItem = None
        self.path = None
        self.fpath = None
        self.current = ""
        super().__init__(parent)
        self.setWindowIcon(QtGui.QIcon("images/file.png"))
        self.download = QtGui.QIcon("images/download.png")
        self.upload = QtGui.QIcon("images/upload.png")
        self.LOAD_dict = {self.DOWNLOAD: self.download,
                          self.UPLOAD: self.upload}
        self.save_path = _save_path
        self.pathdict = {}
        self.infodict = {}
        self.setObjectName("FileDisplayWindow")
        self.resize(666, 421)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        self.setFont(font)

        self.setWindowTitle(QtCore.QCoreApplication.translate("Dialog", "Files"))

        self.itemClicked.connect(self.fileClicked)

        self.menu = QtWidgets.QMenu(self)
        open_file = QtWidgets.QAction(QtGui.QIcon("images/file.png"), '打开文件', self)
        open_file.triggered.connect(self.startfile)
        self.menu.addAction(open_file)
        open_path = QtWidgets.QAction(QtGui.QIcon("images/folder.png"), '打开文件夹', self)
        open_path.triggered.connect(self.startpath)
        self.menu.addAction(open_path)

        QtCore.QMetaObject.connectSlotsByName(self)

    def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
        super().mousePressEvent(event)
        if event.button() == QtCore.Qt.RightButton and self.itemAt(event.pos()):
            item = self.itemAt(event.pos())
            index: int = item.index_name
            self.fpath = self.pathdict[index]
            self.path = os.path.dirname(self.fpath)
            self.menu.exec(event.globalPos())

    @QtCore.pyqtSlot(str, int, int, tuple)
    def new_file(self, name, total, size, info):
        self.activateWindow()  # 窗口置顶

        index = len(self.infodict)
        _type, local_file = info

        _c = _cSpeed(total)

        layout = FileListWidget.ListWidgetLayout(name, _c)
        self.pathdict[index] = local_file
        self.infodict[index] = (_c, name, os.path.dirname(local_file))
        item = FileListWidget.ListItem(self, self.LOAD_dict.get(_type, self.UPLOAD), index, layout)
        self.show()

    @QtCore.pyqtSlot(int)
    def update_file(self, index: int):
        _c: _cSpeed = self.infodict[index][0]
        _c.update_value(1)

    def fileClicked(self, item: ListItem):
        index = item.index_name
        self.dialog = ProgressDialog(*self.infodict[index])
        self.dialog_index = index

    def startfile(self, *args):
        if isinstance(self.fpath, str) and os.path.isfile(self.fpath):
            os.startfile(self.fpath)

    def startpath(self, *args):
        if isinstance(self.path, str) and os.path.isdir(self.path):
            os.startfile(self.path)

    def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
        super(FileListWidget, self).mouseMoveEvent(event)
        self.x, self.y = event.x(), event.y()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    a = FileListWidget(os.path.join(os.path.dirname(os.path.realpath(__file__)), "database", "resource"))
    a.new_file("asdf", 1010, 11111, (0, "C:/users/zhnwe/desktop/1.rte"))
    a.executeDelayedItemsLayout() # 或者 show()
    for x in range(100):
        a.update_file(0)
    app.exec_()

依赖项目文件

ImageLoader.py

图片文件位于ServerProject项目内的 user > images > filetype
地址位于 https://gitcode.net/m0_60394896/python

import os

path = "images/filetype"
unknown = os.path.join(path, "unknown.png").replace("\\", "/")
filedict = {}


def join(filename):
    return os.path.join(path, filename).replace("\\", "/")


def get_suffix_img(suf):
    return filedict.get(suf, unknown)


def get_suf(filename):
    _, suf = os.path.splitext(filename)
    return suf.lstrip(".").lower()


def get(filename):
    return get_suffix_img(get_suf(filename))


for file in os.listdir(path):
    filepath = join(file)
    filetype, _ = os.path.splitext(file)
    filedict[filetype.lower()] = filepath

functions.py

base = 1024


def _conv(value: (float, int)) -> str:
    value = float(value)
    if value.is_integer():
        return str(int(value))
    else:
        return str(round(value, 1))


def convert(byte, fine=False):
    """
    位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位。
    字节 byte:8个二进制位为一个字节(B),最常用的单位。
    其中1024=2^10 ( 2 的10次方),
    1KB (Kilo byte 千字节)=1024B,
    1MB (Mega byte 兆字节 简称“兆”)=1024KB,
    1GB (Giga byte 吉字节 又称“千兆”)=1024MB,
    1TB (Trillion byte 万亿字节 太字节)=1024GB,
    1PB(Peta byte 千万亿字节 拍字节)=1024TB,
    1EB(Exa byte 百亿亿字节 艾字节)=1024PB"""
    if not isinstance(byte, (int, float)):
        byte = len(byte)
    DEI = f"{byte} bytes"
    units = ["b",
             "Kb",
             "Mb",
             "Gb",
             "Tb",
             "Pb",
             "Eb"]
    index = 0
    while True:
        if byte < 1024 or index + 1 >= len(units):
            break
        byte /= base
        index += 1

    if fine:
        return f"{_conv(byte)}{units[index]}({DEI})"
    else:
        return f"{_conv(byte)}{units[index]}"


def to_logging(logger):
    def log(command):
        def _exec_func(*args, **kwargs):
            try:
                _result = command(*args, **kwargs)
                if _result is None:
                    return True
                return _result
            except:
                logger.exception(str())
        return _exec_func
    return log

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:47:30  更:2022-07-20 18:48:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 3:17:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计