问题:我正在尝试实现一个缩略图查看器,其中每个项目(即缩略图及其页码标签)都具有固定大小。我正在尝试缩放图像,以便它们保持这些项目内的纵横比。然而,大多数图像在两个维度上都显得有些裁剪。
期望的结果:缩略图被缩放,没有任何裁剪,并在其项目对象内居中对齐(水平和垂直),最好页码标签距离父项目的底部边框有固定的像素数。
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_())
您正在像这样缩放(显示两个图片尺寸的示例):
(在电子表格的帮助下):
最大宽度 | 最大高度 | 图片宽度 | 图片高度 | 比例因子 | 新宽度 | 新高度 |
---|---|---|---|---|---|---|
220 | 190 | 300 | 600 | 0.316666667 | 95 | 190 |
220 | 190 | 600 | 300 | 0.366666667 | 220 | 110 |
当您在 200x190 的固定窗口中显示原始尺寸为 300x600 的图片,将其大小调整为 95x190 时,您可能确实会得到裁剪后的结果。
您需要以调整后的尺寸(95x190)显示图片,而无需进一步调整其大小。 (其他图片尺寸也一样。)