后台工作者填充 QListView 缩略图

Background worker populate QListView thumbnails

我有一个简单的 QListview,它显示项目名称列表。下载后,我想显示每个项目的缩略图。我如何执行以下操作,因为我刚开始使用后台工作人员之类的东西,我不确定如何实现。

这解释了我认为最好的方法...

您可以使用 QNetworkAccessManager 进行异步下载,而不是使用后台工作程序。

from dataclasses import dataclass
from functools import cached_property
import sys

from PySide2 import QtCore, QtGui, QtWidgets, QtNetwork


@dataclass
class IconDownloader(QtCore.QObject):
    url: QtCore.QUrl
    index: QtCore.QPersistentModelIndex
    _parent: QtCore.QObject = None

    def __post_init__(self):
        super().__init__()
        self.setParent(self._parent)

    @cached_property
    def network_manager(self):
        manager = QtNetwork.QNetworkAccessManager()
        manager.finished.connect(self._handle_finished)
        return manager

    def start(self):
        if self.index.isValid():
            request = QtNetwork.QNetworkRequest(self.url)
            request.setAttribute(
                QtNetwork.QNetworkRequest.FollowRedirectsAttribute, True
            )
            self.network_manager.get(request)

    def _handle_finished(self, reply):
        if reply.error() == QtNetwork.QNetworkReply.NoError:
            pixmap = QtGui.QPixmap()
            ok = pixmap.loadFromData(reply.readAll())
            if ok and self.index.isValid():
                model = self.index.model()
                model.setData(
                    QtCore.QModelIndex(self.index), pixmap, QtCore.Qt.DecorationRole
                )
        else:
            print(reply.error(), reply.errorString())
        reply.deleteLater()
        self.deleteLater()


class ExampleDialog(QtWidgets.QDialog):
    def __init__(self):
        super(ExampleDialog, self).__init__()

        self.itemModel = QtGui.QStandardItemModel()

        self.uiListView = QtWidgets.QListView()
        # self.uiListView.setViewMode(QtWidgets.QListView.IconMode)
        self.uiListView.setIconSize(QtCore.QSize(80, 60))  # set icon size
        self.uiListView.setGridSize(QtCore.QSize(90, 70))  # set icon grid display
        self.uiListView.setModel(self.itemModel)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.addWidget(self.uiListView)

        self.populateImages()

    def populateImages(self):
        for x in range(20):
            url = f"https://picsum.photos/id/{x}/80/60.jpg"
            item = QtGui.QStandardItem(f"x")
            self.itemModel.appendRow(item)
            downloader = IconDownloader(
                QtCore.QUrl(url),
                QtCore.QPersistentModelIndex(self.itemModel.indexFromItem(item)),
                self,
            )
            downloader.start()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = ExampleDialog()
    window.show()
    window.raise_()
    sys.exit(app.exec_())