如何在自定义列表小部件中正确缩放缩略图?

问题描述 投票:0回答:1

问题:我正在尝试实现一个缩略图查看器,其中每个项目(即缩略图及其页码标签)都具有固定大小。我正在尝试缩放图像,以便它们保持这些项目内的纵横比。然而,大多数图像在两个维度上都显得有些裁剪。

MWE - Main Window

期望的结果:缩略图被缩放,没有任何裁剪,并在其项目对象内居中对齐(水平和垂直),最好页码标签距离父项目的底部边框有固定的像素数。

MWE:

import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QSplitter

from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QPixmap

from PyQt5.QtWidgets import QListWidget, QVBoxLayout, QListWidgetItem, QListView, QAbstractItemView, QLabel

class CustomListWidget(QListWidget):
    def dropEvent(self, event):
        super().dropEvent(event)
        self.updatePageNumbers()

    def updatePageNumbers(self):
        for index in range(self.count()):
            item = self.item(index)
            widget = self.itemWidget(item)
            if widget is not None:  
                number_label = widget.findChild(QLabel, 'PageNumberLabel')
                if number_label:  
                    number_label.setText(str(index + 1))
            else:
                print(f"No widget found for item at index {index}")

class ThumbnailViewer(QWidget):
    def __init__(self):
        super().__init__()
        # self.iconSize = QSize(200, 220)
        # self.itemSize = QSize(220, 250)
        self._initUI()

    def _initUI(self):
        vbox = QVBoxLayout(self)
        self.listWidget = CustomListWidget()  
        self.listWidget.setDragDropMode(QAbstractItemView.InternalMove)
        self.listWidget.setFlow(QListView.LeftToRight)
        self.listWidget.setWrapping(True)
        self.listWidget.setResizeMode(QListView.Adjust)
        self.listWidget.setMovement(QListView.Snap)
        # self.listWidget.setIconSize(self.iconSize)

        self.listWidget.setStyleSheet("""
            QListWidget::item {
                border: 1px solid red;
            }
        """)

        folder = os.path.join(os.getcwd(), 'thumbs')
        files = [f for f in os.listdir(folder) if f.lower().endswith(('.png', '.jpg', '.jpeg')) and not f.startswith('.')]

        for idx, file in enumerate(files, start=1):  
            item, widget = self.loadImageItem(file, idx, folder=folder)
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, widget)
            print(f"Adding thumbnail to ThumbnailViewer: {file}")

        vbox.addWidget(self.listWidget)
        self.setLayout(vbox)

    def loadImageItem(self, file, pageNum, folder=None):
        widget = QWidget()
        iconLabel = QLabel()
        path = os.path.join(folder, file) if folder else file
        pixmap = QPixmap(path)

        max_width = 220
        max_height = 190  

        aspect_ratio = pixmap.width() / pixmap.height()
        if aspect_ratio > 1:  
            scale_factor = max_width / pixmap.width()
        else:  
            scale_factor = max_height / pixmap.height()

        new_width = int(pixmap.width() * scale_factor)
        new_height = int(pixmap.height() * scale_factor)

        scaled_pixmap = pixmap.scaled(new_width, new_height, Qt.KeepAspectRatio)
        iconLabel.setPixmap(scaled_pixmap)
        iconLabel.setAlignment(Qt.AlignCenter)

        numberLabel = QLabel(str(pageNum))
        numberLabel.setObjectName('PageNumberLabel')
        numberLabel.setAlignment(Qt.AlignHCenter)

        layout = QVBoxLayout()
        layout.addWidget(iconLabel)
        layout.addWidget(numberLabel)
        widget.setLayout(layout)

        item = QListWidgetItem()
        item.setSizeHint(QSize(220, 250))  
        return item, widget

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Thumbnail Viewer Test")

        central_widget = QWidget()
        layout = QVBoxLayout(central_widget)

        # Thumbnail Viewer
        self.thumbnail_viewer = ThumbnailViewer()
        layout.addWidget(self.thumbnail_viewer)

        # Add a blank space
        blank_space = QLabel("Blank Space")
        blank_space.setAlignment(Qt.AlignCenter)
        layout.addWidget(blank_space)

        self.setCentralWidget(central_widget)

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setGeometry(100, 100, 800, 600)
    window.show()
    sys.exit(app.exec_())
pyqt5 custom-widgets
1个回答
0
投票

您正在像这样缩放(显示两个图片尺寸的示例):

(在电子表格的帮助下):

最大宽度 最大高度 图片宽度 图片高度 比例因子 新宽度 新高度
220 190 300 600 0.316666667 95 190
220 190 600 300 0.366666667 220 110

当您在 200x190 的固定窗口中显示原始尺寸为 300x600 的图片,将其大小调整为 95x190 时,您可能确实会得到裁剪后的结果。

您需要以调整后的尺寸(95x190)显示图片,而无需进一步调整其大小。 (其他图片尺寸也一样。)

© www.soinside.com 2019 - 2024. All rights reserved.