How to use QScrollArea to make scrollbars appear
Solution 1:
Since many questions wonder how to use a QScrollArea that many widgets have, I will take the license to explain the various forms in detail and use them as a canonical answer for future readers.
QScrollArea only allows placing a container widget so the other widgets must be placed as children of the container widget.
And to place the widgets as children of another there are 2 possibilities:
1. Use a QLayout:
QLayouts allow you to automate the geometry of the widgets based on the QSizePolicy, strecth, sizeHint, etc. So in that case it's simple: Just set the widgetResizable property to True.
import sys
from PyQt5 import QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(True)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# Set widgets via layout
lay = QtWidgets.QVBoxLayout(container)
lay.setContentsMargins(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text)
lay.addWidget(label)
lay.addStretch()
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
2. Set the widgets directly without layouts:
In this case you must calculate the minimum geometry that contains the internal widgets and set the size in the container, also you must set the widgetResizable property to False:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(False)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# calculate geometry
geometry = QtCore.QRect(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text, container)
label.adjustSize()
label.move(geometry.bottomLeft())
geometry |= label.geometry()
geometry.setTopLeft(QtCore.QPoint(0, 0))
container.resize(geometry.size())
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())