PyQt5. QListView менеджер файлов картинок. Как заменить иконки на миниатюры изображений png?
Создал класс с моделью QFileSystemModel. Проблема - нужно чтобы вместо иконок отображались миниатюры (как в обычном файловом менеджере Windows).
class MyFileManager(QListView):
def __init__(self):
super().__init__()
self.mdl = QFileSystemModel()
self.mdl.setRootPath(QDir.rootPath())
self.setModel(self.mdl)
self.setWindowTitle('менеджер файлов')
self.setRootIndex(self.mdl.index(QDir.currentPath()))
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
self.setDragEnabled(True)
self.setViewMode(QListView.IconMode)
self.setMovement(QListView.Free)
self.setGridSize(QSize(100, 100))
self.setIconSize(QSize(80, 80))
Пробовал создать дополнительный класс, его средствами получается поменять иконки на миниатюры. Но тогда пропадает возможность Drag & Drop.
class MyListModel(QAbstractListModel):
def __init__(self, datain, parent=None, *args):
""" datain: a list where each item is a row
"""
QAbstractListModel.__init__(self, parent, *args)
self.listdata = datain
def rowCount(self, parent=QModelIndex()):
return len(self.listdata)
def data(self, index, role):
if index.isValid() and role == Qt.DecorationRole:
return QIcon(QPixmap(self.listdata[index.row()]))
if index.isValid() and role == Qt.DisplayRole:
return QVariant(path.splitext(path.split(self.listdata[index.row()])[-1])[0])
else:
return QVariant()
Что можно сделать, чтобы сохранить драг-дроп и заменить иконки на миниатюры?
Предпочтительно с моделью QFileSystemModel.
Ответы (2 шт):
Решено! Необходимо использовать собственный класс MyIconProvider(QFileIconProvider) и установить setIconProvider(MyIconProvider())
class MyIconProvider(QFileIconProvider):
def __init__(self):
super().__init__()
def icon(self, type):
get_path = type.filePath() # получаем путь к файлу
if get_path.endswith(".png"): # отфильтровываем для каких будут миниатюры
tmp_pxmp = QPixmap(QSize(64,64))
tmp_pxmp.load(get_path) # загружаем картинку
return QIcon(tmp_pxmp) # и возвращаем в виде иконки
else:
return super().icon(type)
В своей структуре добавляем строку назначения провайдера:
self.mdl.setIconProvider(MyIconProvider())
В итоге мой рабочий код выглядит так:
class MyIconProvider(QFileIconProvider):
def __init__(self):
super().__init__()
def icon(self, type: 'QFileIconProvider.IconType'):
get_path = type.filePath()
if get_path.endswith(".png"):
tmp_pxmp = QPixmap(QSize(64,64))
tmp_pxmp.load(get_path)
return QIcon(tmp_pxmp)
else:
return super().icon(type)
class MyFileManager(QListView):
def __init__(self):
super().__init__()
self.mdl = QFileSystemModel()
self.mdl.setRootPath(QDir.rootPath())
self.mdl.setIconProvider(MyIconProvider()) # <--------------
self.setWindowTitle('менеджер файлов')
self.setModel(self.mdl)
self.setRootIndex(self.mdl.index(QDir.currentPath()))
self.setViewMode(QListView.IconMode)
self.setMovement(QListView.Snap)
self.setGridSize(QSize(100, 100))
self.setIconSize(QSize(80, 80))
Да, то что вы предложили работает. А беда в том, что есть битые изображения.
bool QPixmap::load(const QString &fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor)
Загружает растровое изображение из файла с данным
fileName. \
- Возвращает истину, если растровое изображение было успешно загружено;
- в противном случае делает растровое изображение недействительным и возвращает false.
import sys
from PyQt5.Qt import *
class MyIconProvider(QFileIconProvider):
def __init__(self):
super().__init__()
def icon(self, _type: 'QFileIconProvider.IconType'):
get_path = _type.filePath()
if get_path.endswith(".png") or \
get_path.endswith(".jpg") or\
get_path.endswith(".gif"):
tmp_pxmp = QPixmap(QSize(64, 64))
pix = tmp_pxmp.load(get_path) # +++ = pix
if pix: # +++
return QIcon(tmp_pxmp) # +++
else:
print(f'Это изображение битое !!! -> {pix} -> {get_path}') # +++ !!!
return super().icon(_type) # +++
else:
return super().icon(_type)
class MyFileManager(QListView):
def __init__(self):
super().__init__()
self.mdl = QFileSystemModel()
self.mdl.setRootPath(QDir.rootPath())
self.mdl.setIconProvider(MyIconProvider()) # <---
self.setWindowTitle('менеджер файлов')
self.setModel(self.mdl)
self.setRootIndex(self.mdl.index(QDir.currentPath()))
self.setViewMode(QListView.IconMode)
self.setMovement(QListView.Snap)
self.setGridSize(QSize(100, 100))
self.setIconSize(QSize(80, 80))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyFileManager()
window.show()
sys.exit(app.exec_())
