You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义List Widget中正确缩放缩略图?

解决缩略图裁剪与布局对齐问题

问题根源

原代码存在几个关键问题导致图片裁剪和布局不符合预期:

  • 手动计算缩放因子易出错,未利用Qt内置的自适应缩放逻辑
  • 图片标签未设置合适的尺寸策略,无法在布局内自适应空间并居中图片
  • 布局未配置拉伸项,导致页码标签无法固定在底部

修改方案

以下是调整后的完整代码,关键改动已标注:

import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QListWidget, QListWidgetItem, QListView, QAbstractItemView, QLabel, QSizePolicy
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QPixmap

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._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.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  

        # 简化缩放逻辑:直接用Qt内置方法保持比例并平滑缩放
        scaled_pixmap = pixmap.scaled(max_width, max_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        iconLabel.setPixmap(scaled_pixmap)
        iconLabel.setAlignment(Qt.AlignCenter)
        
        # 设置图片标签尺寸策略,让它占据布局内可用空间
        iconLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # 确保图片不被拉伸(默认值,明确设置更清晰)
        iconLabel.setScaledContents(False)

        numberLabel = QLabel(str(pageNum))
        numberLabel.setObjectName('PageNumberLabel')
        numberLabel.setAlignment(Qt.AlignHCenter)
        # 设置页码标签与底部的固定距离
        numberLabel.setStyleSheet("margin-bottom: 8px;")

        layout = QVBoxLayout(widget)
        # 去掉布局默认边距,让内容贴合项边框
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(iconLabel)
        # 添加拉伸项,将页码标签固定在底部
        layout.addStretch()
        layout.addWidget(numberLabel)

        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)

        self.thumbnail_viewer = ThumbnailViewer()
        layout.addWidget(self.thumbnail_viewer)

        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_())

关键改动说明

  • 缩放逻辑简化:直接调用pixmap.scaled()并传入Qt.KeepAspectRatio,Qt自动计算最优缩放比例,避免手动计算误差
  • 图片标签尺寸策略:设置Expanding策略让标签占据所有可用空间,配合AlignCenter确保图片居中
  • 布局拉伸项:layout.addStretch()让图片区域自动填充上方空间,页码标签被固定在底部
  • 固定页码距离:用样式表设置margin-bottom,确保页码与项底部保持固定像素距离
  • 去除布局边距:消除默认留白,让内容更贴合项的边框

内容的提问来源于stack exchange,提问作者MrVocabulary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:35:06