Как использовать QScrollArea для отображения полос прокрутки

#python #scroll #pyqt #widget #scrollbar

Вопрос:

Я пытаюсь создать область прокрутки с вертикальным расположением, используя pyqt5, и я помещаю внутри некоторые метки. Я знаю, что даже если это вертикальный макет, он должен прокручиваться горизонтально, если текст не подходит. Но что бы я ни пытался, это не дает мне прокручиваться.

Это код, который я использую:

 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_())
 

Вот как это должно выглядеть:

введите описание изображения здесь

Вот как это выглядит:

введите описание изображения здесь

Я надеюсь, что мой вопрос ясен

Комментарии:

1. Я попытаюсь сделать скриншот того, как это должно быть и как это на самом деле

2. скриншоты помогают, но это не то, о чем я вас просил

3. Я знаю, но я действительно не знаю, как каким-либо образом упростить вопрос. Я думаю, что скриншоты намного лучше подходят для понимания того, чего я пытаюсь достичь

4. Я понимаю проблему в том смысле, что это то, что вы получаете и что вы хотите получить благодаря своим изображениям, но этого недостаточно, так как это не позволяет мне понять причину ошибки, по этой причине мне потребовался MRE. Если вы не предоставите его, я проголосую за то, чтобы закрыть ваш вопрос и продолжить свой путь

5. Как я могу изменить вопрос, чтобы он соответствовал MRE? Я попытался включить только необходимый код, связанный с проблемой. Я постараюсь включить более подробную информацию, извините за неудобства

Ответ №1:

Поскольку многие вопросы задаются вопросом, как использовать QScrollArea, который есть у многих виджетов, я возьму лицензию, чтобы подробно объяснить различные формы и использовать их в качестве канонического ответа для будущих читателей.

QScrollArea позволяет размещать только виджет контейнера, поэтому другие виджеты должны быть размещены как дочерние элементы виджета контейнера.

И разместить виджеты в качестве дочерних элементов другого есть 2 возможности:

1. Используйте QLayout:

QLayouts позволяют автоматизировать геометрию виджетов на основе QSizePolicy, strecth, sizeHint и т.д. Так что в этом случае все просто: просто установите свойству widgetResizable значение 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. Установите виджеты непосредственно без макетов:

В этом случае вы должны рассчитать минимальную геометрию, содержащую внутренние виджеты, и установить размер в контейнере, также вы должны установить свойство widgetResizable в значение 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_())