Позиционирование элементов в PyQT

Хотел бы узнать как можно удобно позиционировать элементы, если пишешь небольшие классы без использования Qt Designer.
Часто видел, что люди, которые здесь отвечают на вопросы по Qt пишут похожим образом.

from PyQt5 import QtWidgets


class HelpDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(HelpDialog, self).__init__(parent)

        layout = QtWidgets.QGridLayout(self)

        text_widget = QtWidgets.QLabel('anytext')
        btnOk = QtWidgets.QPushButton("Ок", clicked=self.hide)

        layout.addWidget(text_widget, 0, 0, 1, 1)
        layout.addWidget(btnOk, 3, 1, 1, 1)

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

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

Layout Management

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

...

Это не зависит от размера класса, его просто надо применять на практике.
Вот вам базовый пример - смотрите и изучайте.

from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
    QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
    QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
    QVBoxLayout)


class Dialog(QDialog):
    NumGridRows = 3
    NumButtons  = 4

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

        self.createMenu()
        self.createHorizontalGroupBox()
        self.createGridGroupBox()
        self.createFormGroupBox()

        bigEditor = QTextEdit()
        bigEditor.setPlainText(
            "Этот виджет занимает все оставшееся пространство "
            "в макете верхнего уровня."
        )

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        mainLayout = QVBoxLayout()
        mainLayout.setMenuBar(self.menuBar)
        mainLayout.addWidget(self.horizontalGroupBox)
        mainLayout.addWidget(self.gridGroupBox)
        mainLayout.addWidget(self.formGroupBox)
        mainLayout.addWidget(bigEditor)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Basic Layouts")

    def createMenu(self):
        self.menuBar = QMenuBar()

        self.fileMenu = QMenu("&File", self)
        self.exitAction = self.fileMenu.addAction("E&xit")
        self.menuBar.addMenu(self.fileMenu)

        self.exitAction.triggered.connect(self.accept)

    def createHorizontalGroupBox(self):
        self.horizontalGroupBox = QGroupBox("Horizontal layout")
        layout = QHBoxLayout()

        for i in range(Dialog.NumButtons):
            button = QPushButton("Button %d" % (i + 1))
            layout.addWidget(button)

        self.horizontalGroupBox.setLayout(layout)

    def createGridGroupBox(self):
        self.gridGroupBox = QGroupBox("Grid layout")
        layout = QGridLayout()

        for i in range(Dialog.NumGridRows):
            label = QLabel("Line %d:" % (i + 1))
            lineEdit = QLineEdit()
            layout.addWidget(label,    i + 1, 0)
            layout.addWidget(lineEdit, i + 1, 1)

        self.smallEditor = QTextEdit()
        self.smallEditor.setPlainText(
            "Этот виджет занимает около двух третей "
            "макета сетки. \n Смотрим соотношение `setColumnStretch`!"
        )

        layout.addWidget(self.smallEditor, 0, 2, 5, 1)   # 0, 2, 4, 1

        # QGridLayout.setColumnStretch(column, stretch)
        # Устанавливает растягивающий коэффициент столбца столбца для растягивания. 
        # Первый столбец - номер 0.
        #layout.setColumnStretch(0, 1)      # label
        layout.setColumnStretch(1, 10)      # lineEdit
        layout.setColumnStretch(2, 20)      # smallEditor
        self.gridGroupBox.setLayout(layout)

    def createFormGroupBox(self):
        self.formGroupBox = QGroupBox("Form layout")
        layout = QFormLayout()
        layout.addRow(QLabel("Line 1:"), QLineEdit())
        layout.addRow(QLabel("Строка 2, длинный текст:"), QComboBox())
        layout.addRow(QLabel("Line 3:"), QSpinBox())
        self.formGroupBox.setLayout(layout)


if __name__ == '__main__':
    import sys
    app    = QApplication(sys.argv)
    dialog = Dialog()
    sys.exit(dialog.exec_())

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

→ Ссылка