Как поместить QGridLayout в QScrollArea, а QScrollAreа в QHBoxLayout?

У меня есть код, который я оставлю ниже. В классе MyWindow я создаю два контейнера:

  1. Первый контейнер box является QHBoxLayout'ом. Второй контейнер box1 является QGridLayout'ом.
  2. В box1 я помещаю 16 кнопок QPushButton.
  3. В box я помещаю box1 и кнопку button.

Мне бы хотелось поместить контейнер box1 в область с полосой прокрутки, а эту область в box. Как я понял, в PyQt она называется QScrollArea. Нарисовал схему для наглядности:

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

Я нашел примеры, где QScrollArea используют в качестве главного окна. Это мне не подходит. Пожалуйста, подскажите, как сделать то, что описывалоcь выше?

Мой код:

from PyQt5 import QtCore, QtWidgets, QtGui

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(250, 150)
        self.setMaximumSize(250, 150)

        self.box = QtWidgets.QHBoxLayout()

        self.button = QtWidgets.QPushButton('Button')

        self.box1 = QtWidgets.QGridLayout()

        self.button1 = QtWidgets.QPushButton('Button1')
        self.button2 = QtWidgets.QPushButton('Button2')
        self.button3 = QtWidgets.QPushButton('Button3')
        self.button4 = QtWidgets.QPushButton('Button4')
        self.button5 = QtWidgets.QPushButton('Button5')
        self.button6 = QtWidgets.QPushButton('Button6')
        self.button7 = QtWidgets.QPushButton('Button7')
        self.button8 = QtWidgets.QPushButton('Button8')
        self.button9 = QtWidgets.QPushButton('Button9')
        self.button10 = QtWidgets.QPushButton('Button10')
        self.button11 = QtWidgets.QPushButton('Button11')
        self.button12 = QtWidgets.QPushButton('Button12')
        self.button13 = QtWidgets.QPushButton('Button13')
        self.button14 = QtWidgets.QPushButton('Button14')
        self.button15 = QtWidgets.QPushButton('Button15')
        self.button16 = QtWidgets.QPushButton('Button16')

        self.box1.addWidget(self.button1, 0, 0)
        self.box1.addWidget(self.button2, 1, 0)
        self.box1.addWidget(self.button3, 2, 0)
        self.box1.addWidget(self.button4, 3, 0)
        self.box1.addWidget(self.button5, 4, 0)
        self.box1.addWidget(self.button6, 5, 0)
        self.box1.addWidget(self.button7, 6, 0)
        self.box1.addWidget(self.button8, 7, 0)
        self.box1.addWidget(self.button9, 8, 0)
        self.box1.addWidget(self.button10, 9, 0)
        self.box1.addWidget(self.button11, 10, 0)
        self.box1.addWidget(self.button12, 11, 0)
        self.box1.addWidget(self.button13, 12, 0)
        self.box1.addWidget(self.button14, 13, 0)
        self.box1.addWidget(self.button15, 14, 0)
        self.box1.addWidget(self.button16, 15, 0)

        self.box.addLayout(self.box1)
        self.box.addWidget(self.button)
        self.setLayout(self.box)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Обычно это делается так:

from PyQt5 import QtCore, QtWidgets, QtGui

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(250, 150)
        self.setMaximumSize(250, 150)

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        scrollArea = QtWidgets.QScrollArea()
        content_widget = QtWidgets.QWidget()
        scrollArea.setWidget(content_widget)
        scrollArea.setWidgetResizable(True)
        self.box1 = QtWidgets.QGridLayout(content_widget) 
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        

        self.button = QtWidgets.QPushButton('Button')

        self.button1 = QtWidgets.QPushButton('Button1')
        self.button2 = QtWidgets.QPushButton('Button2')
        self.button3 = QtWidgets.QPushButton('Button3')
        self.button4 = QtWidgets.QPushButton('Button4')
        self.button5 = QtWidgets.QPushButton('Button5')
        self.button6 = QtWidgets.QPushButton('Button6')
        self.button7 = QtWidgets.QPushButton('Button7')
        self.button8 = QtWidgets.QPushButton('Button8')
        self.button9 = QtWidgets.QPushButton('Button9')
        self.button10 = QtWidgets.QPushButton('Button10')
        self.button11 = QtWidgets.QPushButton('Button11')
        self.button12 = QtWidgets.QPushButton('Button12')
        self.button13 = QtWidgets.QPushButton('Button13')
        self.button14 = QtWidgets.QPushButton('Button14')
        self.button15 = QtWidgets.QPushButton('Button15')
        self.button16 = QtWidgets.QPushButton('Button16')

        self.box1.addWidget(self.button1, 0, 0)
        self.box1.addWidget(self.button2, 1, 0)
        self.box1.addWidget(self.button3, 2, 0)
        self.box1.addWidget(self.button4, 3, 0)
        self.box1.addWidget(self.button5, 4, 0)
        self.box1.addWidget(self.button6, 5, 0)
        self.box1.addWidget(self.button7, 6, 0)
        self.box1.addWidget(self.button8, 7, 0)
        self.box1.addWidget(self.button9, 8, 0)
        self.box1.addWidget(self.button10, 9, 0)
        self.box1.addWidget(self.button11, 10, 0)
        self.box1.addWidget(self.button12, 11, 0)
        self.box1.addWidget(self.button13, 12, 0)
        self.box1.addWidget(self.button14, 13, 0)
        self.box1.addWidget(self.button15, 14, 0)
        self.box1.addWidget(self.button16, 15, 0)

        self.box = QtWidgets.QHBoxLayout()
#        self.box.addLayout(self.box1)                           # ---
        self.box.addWidget(scrollArea)                           # +++

        self.box.addWidget(self.button)
        self.setLayout(self.box)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())

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


Update

Динамическое размещение виджетов, вам видимо тоже пригодится. А то я не представляю размеры вашей программы если вы захотите разместить больше кнопок.

Ваша программа может выглядеть так:

from PyQt5 import QtCore, QtWidgets, QtGui

class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(250, 150)
        self.setMaximumSize(250, 150)

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        scrollArea = QtWidgets.QScrollArea()
        content_widget = QtWidgets.QWidget()
        scrollArea.setWidget(content_widget)
        scrollArea.setWidgetResizable(True)
        self.box1 = QtWidgets.QGridLayout(content_widget) 
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        

        self.button = QtWidgets.QPushButton('Button')

        for n in range(1, 17):
            btn = QtWidgets.QPushButton(
                f'Button{n}',
                clicked=lambda ch, n=n: print(f'Button{n}')
            )
            self.box1.addWidget(btn, n-1, 0)

        self.box = QtWidgets.QHBoxLayout()
#        self.box.addLayout(self.box1)                           # ---
        self.box.addWidget(scrollArea)                           # +++

        self.box.addWidget(self.button)
        self.setLayout(self.box)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())
→ Ссылка