2

I am trying to create a scroll area with a vertical layout using pyqt5, and I am putting inside some labels. I know that even if it is a vertical layout it is supposed to scroll horizontally if the text does not fit. But no matter what I try it does not let me scroll.

This is the code I am using:

class window(QMainWindow):
    def __init__(self):
        super(window, self).__init__()
        self.setGeometry(300, 300, 803, 520)
        self.init_ui()

    def init_ui(self):
        self.teacher_box = QScrollArea(self)
        self.teacher_box.setGeometry(360, 10, 420, 181)
        self.teacher_box.setWidgetResizable(True)
        self.teacher_box.setObjectName("teacher_box")
        self.teacher_box_widget = QWidget()
        self.teacher_box_widget.setGeometry(QtCore.QRect(0, 0, 420, 181))
        self.teacher_box_widget.setObjectName("teacher_box_widget")
        self.verticalLayout = QVBoxLayout(self.teacher_box_widget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.teacher_box.setWidget(self.teacher_box_widget) 
        self.teacher_label = QtWidgets.QLabel(self.teacher_box_widget)
        self.teacher_label.setText("This is a new text label that i created using pyqt5's qscrollarea and now the label is going to get outside the boundaries")
        self.teacher_label.adjustSize()
        self.teacher_label.move(10, 10)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = window()
    win.show()
    sys.exit(app.exec_())

Here is how it should look:

enter image description here

Here is how it looks:

enter image description here

I hope my question is clear

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Simon
  • 107
  • 9
  • I'll try to take a screenshot of how it should be and of how it is actually – Simon Sep 06 '20 at 00:00
  • the screenshots help but it is not what I asked you – eyllanesc Sep 06 '20 at 00:04
  • I know but I really don't know how to make the question simpler in any way. I think the screenshots are a lot better to understanding what I'm trying to achieve – Simon Sep 06 '20 at 00:10
  • I understand the problem in the sense that it is what you get and what you want to get thanks to your images, but that is not enough since it does not allow me to understand the cause of the error, for that reason I have required an MRE. If you do not provide it then I will vote to close your question and go on my way – eyllanesc Sep 06 '20 at 00:12
  • How can I change the question to match the MRE? I tried to include only the necessary code related to the problem. I will try to include more details, sorry for the inconvenience – Simon Sep 06 '20 at 00:16
  • I changed the code so it is a bit easier to understand. Hope this is what you were asking. – Simon Sep 06 '20 at 00:20
  • That is not an MRE, an MRE should allow anyone to copy the code, and then run it without adding anything to reproduce the problem. In your case you can't do it obviously. – eyllanesc Sep 06 '20 at 00:23
  • I think this is now ok. well I hope – Simon Sep 06 '20 at 00:26
  • I have fixed the code that you provide (indentation, typo, etc) that I should not have done since that is your job, a quality question should concern itself with those details. And still I don't reproduce your problem since I get the following: https://i.imgur.com/wTSk9Fg.png – eyllanesc Sep 06 '20 at 00:33
  • It's just because the label is not long enough, but I can set that up manually. If I just increase the length of the label I get this: https://imgur.com/9zuNTYw which is like the example I posted – Simon Sep 06 '20 at 00:40

1 Answers1

4

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_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241