前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python+PyQt5|文件传输测速和计算eta

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

作者头像
zmh-program
发布2023-02-06 10:14:43
3770
发布2023-02-06 10:14:43
举报
文章被收录于专栏:信息技术博客

文章目录

ETAESTIMATED ARRIVAL) 预计到达

  • 在pip中也有eta

计算公式 (v 为速度, sp 为当前进度,st 为总进度,t 为时间):

v=\frac {s_p} {t}
percent = \frac {s_p} {s_t} · 100\%
eta=\frac {s_t - s_p} {v}

eta转换为 00:00:00 的形式,当速度为0和完成时,记为 --:--:--

效果展示

stylesheet (dialog, progressBar)采用渐变 .

这是我原来做的:

代码语言:javascript
复制
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个类中管理.

代码语言:javascript
复制
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

全部代码

代码语言:javascript
复制
# -*- 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

代码语言:javascript
复制
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
代码语言:javascript
复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 效果展示
  • 全部代码
    • 依赖项目文件
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档