Search code examples
pythonpyqtpyqt5qscrollareaqgroupbox

PyQt5 QScrollArea widget with dynamically created GroupBoxes


I'm trying to make a toolbox widget that will do various different things. But I'm having trouble with the layout management regarding the QScrollArea. Following the stripped version of the code I have:

from PyQt5 import QtWidgets
import sys


class MyScrollWidget(QtWidgets.QWidget):

    def __init__(self):
        super(MyScrollWidget, self).__init__()

        scrollArea = QtWidgets.QScrollArea(self)
        top_widget = QtWidgets.QWidget()
        top_layout = QtWidgets.QVBoxLayout()
        for i in range(10):
            group_box = QtWidgets.QGroupBox()

            group_box.setTitle('GroupBox For Item {0}'.format(i))

            layout = QtWidgets.QHBoxLayout(group_box)

            label = QtWidgets.QLabel()
            label.setText('Label For Item {0}'.format(i))
            layout.addWidget(label)

            push_button = QtWidgets.QPushButton(group_box)
            push_button.setText('Run Button')
            push_button.setFixedSize(100, 32)
            layout.addWidget(push_button)

            group_box.setLayout(layout)
            top_layout.addWidget(group_box)

        top_widget.setLayout(top_layout)
        scrollArea.setWidget(top_widget)
        self.resize(200, 500)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    widget = MyScrollWidget()
    widget.show()
    sys.exit(app.exec_())

But this only gives me a small fixed subsection of the widget that scrolled. But what I really wants is the whole widget to be scrollable if the widget/window is smaller than the total size of all the group boxes. I.e I'd like the widget to be used as if it was all fixed width, but if the user resized the widget smaller than that, it would scroll appropriately. I've tried various different methods with no good results so now I'm deferring to those who have more experience with layout management than I. Thank you for your time.


Solution

  • You have to set the scrollArea to MyScrollWidget using a layout.

    from PyQt5 import QtWidgets
    import sys
    
    
    class MyScrollWidget(QtWidgets.QWidget):
    
        def __init__(self):
            super(MyScrollWidget, self).__init__()
            lay = QtWidgets.QVBoxLayout(self)
    
            scrollArea = QtWidgets.QScrollArea()
            lay.addWidget(scrollArea)
            top_widget = QtWidgets.QWidget()
            top_layout = QtWidgets.QVBoxLayout()
    
            for i in range(10):
                group_box = QtWidgets.QGroupBox()
    
                group_box.setTitle('GroupBox For Item {0}'.format(i))
    
                layout = QtWidgets.QHBoxLayout(group_box)
    
                label = QtWidgets.QLabel()
                label.setText('Label For Item {0}'.format(i))
                layout.addWidget(label)
    
                push_button = QtWidgets.QPushButton(group_box)
                push_button.setText('Run Button')
                push_button.setFixedSize(100, 32)
                layout.addWidget(push_button)
    
                top_layout.addWidget(group_box)
    
            top_widget.setLayout(top_layout)
            scrollArea.setWidget(top_widget)
            self.resize(200, 500)
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        widget = MyScrollWidget()
        widget.show()
        sys.exit(app.exec_())