gpt4 book ai didi

python - 如何使小部件的高度与其宽度成固定比例

转载 作者:太空宇宙 更新时间:2023-11-03 16:33:45 25 4
gpt4 key购买 nike

我正在开发一个 PyQt5 应用程序,需要在顶部有一个横幅。横幅只是一个宽图像,其宽度应始终为窗口的宽度,其高度应为固定比例。换句话说,横幅图像的高度应取决于窗口的宽度。横幅下方的小部件(主要内容)应拉伸(stretch)以填充所有可用的垂直空间。

我基本上已经移植了 this SO answer到 PyQt5:

class Banner(QWidget):

def __init__(self, parent):
super(Banner, self).__init__(parent)

self.setContentsMargins(0, 0, 0, 0)

pixmap = QPixmap('banner-1071797_960_720.jpg') # see note below

self._label = QLabel(self)
self._label.setPixmap(pixmap)
self._label.setScaledContents(True)
self._label.setFixedSize(0, 0)
self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

self._resizeImage()

def resizeEvent(self, event):
super(Banner, self).resizeEvent(event)
self._resizeImage()

def _resizeImage(self):
pixSize = self._label.pixmap().size()
pixSize.scale(self.size(), Qt.KeepAspectRatio)
self._label.setFixedSize(pixSize)

(在此示例中,我使用 this 免费横幅图像,但没有什么特别的。)

我已将横幅放入下面的应用程序代码中,其中标签用作主要内容的占位符:

if __name__ == '__main__':

app = QApplication(sys.argv)

widget = QWidget()
widget.setContentsMargins(0, 0, 0, 0)
layout = QVBoxLayout(widget)

banner = Banner(widget)
bannerSizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
bannerSizePolicy.setHeightForWidth(True)
banner.setSizePolicy(bannerSizePolicy)
layout.addWidget(banner)

label = QLabel('There should be a banner above')
label.setStyleSheet('QLabel { background-color: grey; color: white; }');
layout.addWidget(label)
layout.setStretch(0, 1)

widget.resize(320, 200)
widget.move(320, 200)
widget.setWindowTitle('Banner Tester')
widget.show()

sys.exit(app.exec_())

问题是,标签填满了窗口的 100% - 横幅根本不可见。

我尝试了许多不同的尺寸政策和拉伸(stretch)因素,并完全删除了尺寸政策,但还没有找到如何做我需要的事情。横幅中的图像应按比例缩放以适合窗口的宽度,并且标签应填充窗口中剩余的垂直空间。

想法?

最佳答案

@kuba-ober 的评论是正确的:我必须在 Banner 类中实现 hasHeightForWidth()heightForWidth()

这是修改后的代码,它按照我想要的方式工作。所有修改都在代码中添加了注释。

class Banner(QWidget):

def __init__(self, parent):
super(Banner, self).__init__(parent)

self.setContentsMargins(0, 0, 0, 0)

pixmap = QPixmap('banner-1071797_960_720.jpg')

# First, we note the correct proportion for the pixmap
pixmapSize = pixmap.size()
self._heightForWidthFactor = 1.0 * pixmapSize.height() / pixmapSize.width()

self._label = QLabel('pixmap', self)
self._label.setPixmap(pixmap)
self._label.setScaledContents(True)
self._label.setFixedSize(0, 0)
self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

self._resizeImage(self.size())

def hasHeightForWidth(self):
# This tells the layout manager that the banner's height does depend on its width
return True

def heightForWidth(self, width):
# This tells the layout manager what the preferred and minimum height are, for a given width
return math.ceil(width * self._heightForWidthFactor)

def resizeEvent(self, event):
super(Banner, self).resizeEvent(event)
# For efficiency, we pass the size from the event to _resizeImage()
self._resizeImage(event.size())

def _resizeImage(self, size):
# Since we're keeping _heightForWidthFactor, we can code a more efficient implementation of this, too
width = size.width()
height = self.heightForWidth(width)
self._label.setFixedSize(width, height)

if __name__ == '__main__':

app = QApplication(sys.argv)

widget = QWidget()
widget.setContentsMargins(0, 0, 0, 0)
layout = QVBoxLayout(widget)

banner = Banner(widget)
# Turns out we don't need the bannerSizePolicy now
# bannerSizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
# bannerSizePolicy.setHeightForWidth(True)
# banner.setSizePolicy(bannerSizePolicy)
layout.addWidget(banner)

label = QLabel('There should be a banner above')
label.setStyleSheet("QLabel { background-color: grey; color: white; }");
layout.addWidget(label)
layout.setStretch(1, 1)

widget.resize(320, 200)
widget.move(320, 200)
widget.setWindowTitle('Banner Tester')
widget.show()

sys.exit(app.exec_())

关于python - 如何使小部件的高度与其宽度成固定比例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37399515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com