python+PyQt5|文件传输测速和计算eta

9 篇文章 0 订阅
2 篇文章 0 订阅


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=stsp100%
e t a = s t − s p v eta=\frac {s_t - s_p} {v} eta=vstsp
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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值