内容改变大小时如何更新QScrollArea的大小?

How to update QScrollArea size when contents change size?

当我在其中添加一个新的 QPushButton 时,我的 QScrollArea 没有动态更新它的大小。 我想动态地 add/remove QScrollArea 中的一些 QPushButton,但是我的 QScrollArea 没有更新 它的大小。 我希望我的 QScrollArea 始终具有最小可能大小。

使用此代码:

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow,
    QPushButton, QScrollArea, QVBoxLayout)


class MyWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        scroll = QScrollArea(self)
        scroll.setWidgetResizable(True)

        # Contents
        w = QWidget()
        lay = QVBoxLayout(w)
        lay.addWidget(QPushButton('Button'))
        scroll.setWidget(w)

        # Controls
        button_add = QPushButton('Add')
        button_add.clicked.connect(lambda: lay.addWidget(QPushButton('Button')))
        button_del = QPushButton('Del')
        button_del.clicked.connect(lambda: lay.takeAt(0).widget().deleteLater() if lay.count()>0 else None)

        # Main Layout
        vlay = QVBoxLayout()
        vlay.addWidget(scroll)
        vlay.addStretch()
        vlay.addWidget(button_add)
        vlay.addWidget(button_del)

        w = QWidget(self)
        w.setLayout(vlay)
        self.setCentralWidget(w)
        self.resize(200, 300)

if __name__ == '__main__':
    
    app = QApplication([])
    mainWin = MyWindow()
    mainWin.show()
    sys.exit(app.exec_())

我在开始时(左)和添加一些 QPushButton 时(右)得到了这个视图:

所以我有两个问题:

  1. 如何使用最小尺寸的 QScrollArea 启动我的应用程序?
  2. QScrollAre如何动态更新它的大小?

我的理想观点是:

当然,当我添加很多 QPushButton 时,会出现滚动条。

您可以将滚动区域的最大高度设置为等于小部件内容(布局大小 + 边距)。这应该在布局完成它的计算之后完成(例如使用零计时器异步)。

import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QScrollArea, QVBoxLayout

class MyWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        scroll = QScrollArea(self)
        scroll.setWidgetResizable(True)

        # Contents
        w = QWidget()
        lay = QVBoxLayout(w)
        #lay.addWidget(QPushButton('Button'))
        scroll.setWidget(w)

        def updateSize():
            left, top, right, bottom = lay.getContentsMargins()
            hint = lay.sizeHint()
            scroll.setMaximumHeight(hint.height() + top + bottom + 1)

        def addButton():
            lay.addWidget(QPushButton('Button'))
            QTimer.singleShot(0, updateSize)

        def removeButton():
            if lay.count() > 0:
                lay.takeAt(0).widget().deleteLater()
            QTimer.singleShot(0, updateSize)

        addButton()

        # Controls
        button_add = QPushButton('Add')
        button_add.clicked.connect(addButton)
        button_del = QPushButton('Del')
        button_del.clicked.connect(removeButton)

        # Main Layout
        vlay = QVBoxLayout()
        vlay.addWidget(scroll)
        vlay.addStretch(1)
        vlay.addWidget(button_add)
        vlay.addWidget(button_del)
        vlay.setStretch(0,1000)

        w = QWidget(self)
        w.setLayout(vlay)
        self.setCentralWidget(w)
        self.resize(200, 300)

        

if __name__ == '__main__':
    
    app = QApplication([])
    mainWin = MyWindow()
    mainWin.show()
    app.exec()