QScrollArea 不会确认设置小部件的大小

QScrollArea won't acknowledge set widget's size

我正在尝试实现类似 pinterest 的 UI,并且我一直在尝试 PySide 的 FlowLayout 示例。

问题是我正在尝试使用 QScrollArea,但它无法让我充分向下滚动。换句话说,我无法到达要滚动的小部件的底部。

您可以获得孔文件here。如果您下载它并 运行 它,问题将变得非常明显。

我的代码取自 here,并进行了以下修改:

添加了这个class:(它只是让我生成彩色和数字矩形)

class ColoredRectangle(QLabel):
count = 0

def __init__(self, height, color):
    super(ColoredRectangle, self).__init__()

    palette = QPalette()
    palette.setColor(QPalette.Background, color)

    self.setAutoFillBackground(True)
    self.setPalette(palette)

    self.setFixedSize(200, height)
    self.setText(str(ColoredRectangle.count))
    ColoredRectangle.count += 1

现在我要添加矩形而不是按钮...

class Window(QtGui.QWidget):
def __init__(self):
    super(Window, self).__init__()

    flowLayout = FlowLayout()
    flowLayout.addWidget(ColoredRectangle(450, Qt.white))
    flowLayout.addWidget(ColoredRectangle(200, Qt.green))self.setLayout(flowLayout)

    self.setLayout(flowLayout)

    self.setWindowTitle("Flow Layout")

像这样更改了 doLayout 方法:

def doLayout(self, rect):

    if not any(self.itemList):
        return

    firstItem = self.itemList[0]

    x = rect.x()
    y = rect.y()

    wid = firstItem.widget()

    spaceX = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton,
                                                            QtGui.QSizePolicy.PushButton, QtCore.Qt.Horizontal)
    spaceY = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton,
                                                            QtGui.QSizePolicy.PushButton, QtCore.Qt.Vertical)

    itemWidth = firstItem.sizeHint().width()

    # calculate column count

    columnCount = (rect.width() + spaceX) / (itemWidth + spaceX)
    availablePositions = [None] * columnCount

    for i in range(columnCount):
        availablePositions[i] = QPoint(x + i * (itemWidth + spaceX), y)

    for item in self.itemList:

        currentPosition = availablePositions[0]
        currentPositionColumn = 0

        positionColumn = 0
        for position in availablePositions:
            if min(currentPosition.y(), position.y()) != currentPosition.y():
                currentPositionColumn = positionColumn
                currentPosition = position

            positionColumn += 1

        # update available position in column
        itemSize = item.sizeHint()
        availablePositions[currentPositionColumn] = QPoint(currentPosition.x(),
                                                           currentPosition.y() + itemSize.height() + spaceY)

        # place item
        item.setGeometry(QtCore.QRect(currentPosition, itemSize))

最后,我添加了 QScrollArea:

if __name__ == '__main__':
import sys

app = QtGui.QApplication(sys.argv)
mainWin = Window()
scrollArea = QScrollArea()
scrollArea.setWidgetResizable(True)
scrollArea.setWidget(mainWin)
scrollArea.show()
sys.exit(app.exec_())

提前致谢!

好吧,我自己找到了答案...

显然,布局必须定义方法 heightForWidth,据我所知,return 是调整宽度后产生的布局高度。所以...我不得不在 doLayout 的末尾存储新的高度,这样我就可以在需要时 return 它。

这是我在doLayout之后所做的:

self.heightForWidthValue = max(map(lambda position : position.y(), availablePositions))

此外,我在FlowLayout中实现了这些功能:

def hasHeightForWidth(self):
    return True

def heightForWidth(self, width):
    return self.heightForWidthValue

并将0设置为heightForWidthValue的默认值(在FlowLayout->__init__中初始化)。

现在它就像一个魅力:)

Here 的正确代码,如果有人感兴趣的话。