我正在尝试用QHBoxLayout创建QScrollArea,里面包含一行od QWidgets。我希望小部件占据所有可用高度并相应地调整它的大小。
我的小工具是QLabel,里面显示缩放尺寸的QPixmaps。在我的项目中,这些是照片。我实现了heightForWidth和sizeHint方法来实现良好的缩放。我仍然无法达到正确的身高。
默认情况下,小部件会缩放,因此scrollarea不需要滚动条。
不需要滚动条
我使用了滚动小部件的sizePolicy,但只能强制小部件的大小等于sizeHint返回的最大大小。然后水平滚动处于活动状态。
小部件的最大尺寸超出窗口高度
当我更改sizeHint以返回QSize(width(),heightForWidth(width()))时,我发现width()最多返回640像素,而且不会更多。我无法弄清楚640这个限制的来源。
有没有办法在我的布局中删除640px的宽度限制,还是有办法强制小部件扩展到窗口高度?
class ImageWidget(QLabel):
PIXMAP_SIZE = QSize(1000, 500)
def __init__(self, parent=None):
super(ImageWidget, self).__init__(parent)
self._imagePixmap = QtGui.QPixmap(self.PIXMAP_SIZE)
self._imagePixmap.fill(QtGui.QColor(Qt.green))
self.setScaledContents(False)
self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
self.setStyleSheet("border:1px solid red;")
def paintEvent(self, event):
size = self.size()
point = QPoint(0, 0)
scaledPix = self._imagePixmap.scaled(size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
point.setX((size.width() - scaledPix.width())/2)
point.setY((size.height() - scaledPix.height())/2)
QtGui.QPainter(self).drawPixmap(point, scaledPix)
def heightForWidth(self, width):
return self._imagePixmap.height() * width / self._imagePixmap.width() if self._imagePixmap.width() else 0
def hasHeightForWidth(self):
return self._imagePixmap is not None
def sizeHint(self):
return QSize(self.width(), self.heightForWidth(self.width()))
# self.width() has max value of 640 !
#return self.PIXMAP_SIZE
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.seriesLayout = QHBoxLayout()
scrollWidget = QWidget()
scrollWidget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum)
scrollWidget.setLayout(self.seriesLayout)
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setWidget(scrollWidget)
self.setCentralWidget(scroll)
for col in range(5):
self.seriesLayout.addWidget(ImageWidget())
答案 0 :(得分:0)
我最终关注了评论并为我的scrollarea添加了自定义调整大小事件。
我使用viewport().height()
作为首选高度并计算所需宽度,询问每个小部件有关首选widthForHeight()
的信息。这当然只适用于我实现此方法的自定义小部件,但我确信可以扩展为sizeHint()
。
https://github.com/MrCappuccino/Tracey/blob/testing/src/TriangleMesh.cpp#L35-L48
无论如何,这是代码:
class MyScrollArea(QScrollArea):
def __init__(self, parent=None):
super(MyScrollArea, self).__init__(parent)
self.setWidgetResizable(True)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.layout = QHBoxLayout()
self.layout.setSpacing(30)
scroll = QWidget()
scroll.setLayout(self.layout)
self.setWidget(scroll)
def eventFilter(self, obj, event):
if obj == self.widget() and event.type() == QEvent.Resize:
self.widget().resize(self.calcViewportSize())
return True
return super(MyScrollArea, self).eventFilter(obj, event)
def calcViewportSize(self):
height = self.viewport().height()
layoutMargins = self.layout.contentsMargins()
heightForCalc = height - layoutMargins.top() - layoutMargins.bottom()
width = self.calcWidthForHeight(heightForCalc)
return QSize(width, height)
def calcWidthForHeight(self, height):
sum = 0
for wgt in range(self.layout.count()):
sum += self.layout.itemAt(wgt).widget().widthForHeight(height)
if self.layout.count() > 1:
sum += self.layout.spacing() * (self.layout.count()-1)
return sum
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.scroll = MyScrollArea()
self.setCentralWidget(self.scroll)
for col in range(3):
self.scroll.layout.addWidget(ImageWidget())