PyQt6窗口缩放时如何保持页眉与图片紧密贴合
PyQt6 QMainWindow布局同步缩放问题
场景说明
我正在开发一个基于QMainWindow的GUI,布局中垂直排列三个部件:顶部页眉、图片、底部页眉。顶部和底部页眉是带蓝色背景的自定义QWidget,图片通过QLabel加载QPixmap显示(为400x400通用图片)。
当前代码
from PyQt6.QtWidgets import QMainWindow, QApplication, QLabel, QVBoxLayout, QHBoxLayout, QWidget, QSizePolicy, QSpacerItem from PyQt6.QtGui import QPixmap, QColor, QPalette from PyQt6.QtCore import Qt, QSize class ColorWidget(QWidget): def __init__(self, color): super().__init__() self.setAutoFillBackground(True) palette = self.palette() palette.setColor(QPalette.ColorRole.Window, QColor(color)) self.setPalette(palette) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.InitUI() def InitUI(self): layout = QVBoxLayout() layout.setSpacing(0) # Top Header top_header = ColorWidget('blue') top_header_layout = QHBoxLayout() top_header_layout.addWidget(QLabel(parent=top_header, text='Image name')) top_header.setLayout(top_header_layout) layout.addWidget(top_header) # Image self.image_label = QLabel() self.pixmap = QPixmap('Images/Path') self.image_label.setPixmap(self.pixmap) self.image_label.setMinimumSize(QSize(100, 100)) self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.image_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) layout.addWidget(self.image_label) # Bottom Header bottom_header = ColorWidget('blue') bottom_header_layout = QHBoxLayout() bottom_header_layout.addWidget(QLabel(parent=bottom_header, text='Caption')) bottom_header.setLayout(bottom_header_layout) layout.addWidget(bottom_header) central_widget = QWidget() central_widget.setLayout(layout) self.setCentralWidget(central_widget) def resizeEvent(self, event): super().resizeEvent(event) self.adjust_image_size() def adjust_image_size(self): container_size = self.image_label.parentWidget().size() pixmap_width = self.pixmap.width() pixmap_height = self.pixmap.height() max_width = container_size.width() max_height = container_size.height() new_width = min(max_width, pixmap_width) new_height = min(max_height, pixmap_height) if new_width / pixmap_width > new_height / pixmap_height: new_width = new_height * pixmap_width / pixmap_height else: new_height = new_width * pixmap_height / pixmap_width self.image_label.setPixmap(self.pixmap.scaled(int(new_width), int(new_height), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() app.exec()
遇到的问题
- 垂直拉伸窗口时,顶部和底部页眉与图片分离;
- 水平拉伸窗口时,页眉扩展速度快于图片缩放;
- 窗口缩至最小尺寸时,图片呈矩形变形。
期望效果
页眉始终与图片紧密贴合,三者如同单个部件同步缩放。
已尝试的修改
尝试1:限制窗口最大尺寸
# 在MainWindow的Init方法中添加 self.setMaximumWidth(400) self.setMaximumHeight(400)
尝试2:添加间隔项
# 在顶部页眉前添加间隔项 layout.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)) # 在底部页眉后再次添加 layout.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding))
补充尝试(Edit 2)
子类化QWidget管理布局和几何:
class AspectRatioWidget(ColorWidget): def __init__(self, widget, color='#18181d'): super().__init__(color) self.widget = widget layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(widget) self.aspect_ratio = None def resizeEvent(self, event): super().resizeEvent(event) if self.widget.pixmap(): pixmap = self.widget.pixmap() self.aspect_ratio = pixmap.width() / pixmap.height() if self.aspect_ratio: container_width = self.width() container_height = self.height() new_width = container_width new_height = int(container_width / self.aspect_ratio) if new_height > container_height: new_height = container_height new_width = int(container_height * self.aspect_ratio) self.widget.resize(new_width, new_height) self.widget.updateGeometry()
更新主代码部分:
aspect_ratio_widget = AspectRatioWidget(self.image_label) layout.addWidget(aspect_ratio_widget, alignment=Qt.AlignmentFlag.AlignCenter)
内容的提问来源于stack exchange,提问作者DigitalTemplar
相关产品推荐
相关产品推荐

