PyQt QVBoxLayout в Python для вертикального расположения виджетов

 PyQt QVBoxLayout делит родительский виджет на вертикальные блоки и размещает дочерние виджеты последовательно сверху вниз в Python.

Содержание

Что такое PyQt QVBoxLayout

Эта программа иллюстрирует, как использовать класс QVBoxLayout:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons and add them to the layout
        titles = ['Find Next', 'Find All', 'Close']
        buttons = [QPushButton(title) for title in titles]
        for button in buttons:
            layout.addWidget(button)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Выход:

Использование QVBoxLayout

Как это работает.

  • Сначала создайте объект QVBoxLayout:
layout = QVBoxLayout()
  • Затем задайте макет для MainWindow, вызвав его метод setLayout():
self.setLayout(layout)
  • Затем определите список из трех строк, представляющих названия кнопок:
titles = ['Find Next', 'Find All', 'Close']
  • После этого создайте три кнопки(QPushButton) из заголовков списков, используя генератор списков:
buttons = [QPushButton(title) for title in titles]
  • Наконец, добавьте кнопки в макет с помощью цикла for:
for button in buttons:
    layout.addWidget(button)

Выравнивания

QVBoxLayout растягивает каждый тип виджета определенным образом. Например, QVBoxLayout растягивает QPushButton горизонтально, а не вертикально.

Это означает, что при увеличении ширины родительского виджета ширина всех кнопок также увеличивается:

PyQt QVBoxLayout — изменение размера

Однако, когда вы увеличиваете высоту родительского виджета, высота кнопок не меняется. Что еще более важно, QVBoxLayout равномерно распределяет пространство родительского виджета между каждой кнопкой:

PyQt QVBoxLayout — вертикальные пространства

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

Выровнять по низу

Чтобы переместить кнопки в нижнюю часть родительского виджета, добавьте вертикальный разделитель в начале макета с помощью метода addStretch() объекта QVBoxLayout:

PyQt QVBoxLayout — выравнивание нижнего края с помощью вертикального разделителя

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # add a spacer
        layout.addStretch()
        
        # create buttons and add them to the layout
        titles = ['Find Next', 'Find All', 'Close']
        buttons = [QPushButton(title) for title in titles]
        for button in buttons:
            layout.addWidget(button)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Если увеличить высоту окна, вертикальный разделитель растянется до конца QVBoxLayout и оставит достаточно места для кнопок.

Выровнять по верху

Аналогичным образом вы можете добавить вертикальный разделитель в качестве последнего элемента макета, чтобы выдвинуть кнопки наверх, вызвав метод addStretch() после добавления кнопок в макет:

PyQt QVBoxLayout — выравнивание верха с помощью вертикального разделителя

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons and add them to the layout
        titles = ['Find Next', 'Find All', 'Close']
        buttons = [QPushButton(title) for title in titles]
        for button in buttons:
            layout.addWidget(button)

        # add a spacer
        layout.addStretch()

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Выравнивание по центру

Чтобы выровнять кнопки по центру родительского виджета, добавьте вертикальный разделитель в начале и в конце макета, как показано ниже:

PyQt QVBoxLayout — выравнивание по центру

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # add a spacer
        layout.addStretch()

        # create buttons and add them to the layout
        titles = ['Find Next', 'Find All', 'Close']
        buttons = [QPushButton(title) for title in titles]
        for button in buttons:
            layout.addWidget(button)

        # add a spacer
        layout.addStretch()

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Обратите внимание, что вы можете добавить вертикальный разделитель между виджетами в QVBoxLayout. Например, следующий код добавляет вертикальный разделитель между второй и третьей кнопками:

Добавление вертикального разделителя между виджетами в QVBoxLayout

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons
        find_next_btn = QPushButton('Find Next')
        find_all_btn = QPushButton('Find All')
        close_btn = QPushButton('Find All')

        # add the first & second buttons to the layout
        layout.addWidget(find_next_btn)
        layout.addWidget(find_all_btn)

        # add a spacer
        layout.addStretch()

        # add the third button
        layout.addWidget(close_btn)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Установка коэффициентов растяжения макета

Следующая программа отображает три виджета QLabel с разными цветами фона: красным, зеленым и синим, используя QVBoxLayout:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons
        label_1 = QLabel()
        label_1.setStyleSheet('QLabel{background-color:red}')
        label_2 = QLabel()
        label_2.setStyleSheet('QLabel{background-color:green}')
        label_3 = QLabel()
        label_3.setStyleSheet('QLabel{background-color:blue}')

        layout.addWidget(label_1)
        layout.addWidget(label_2)
        layout.addWidget(label_3)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Обратите внимание, что мы используем таблицы стилей для установки цвета фона для виджетов QLabel.

В отличие от виджетов QPushButton, виджеты QLabel растягиваются как по вертикали, так и по горизонтали при изменении размера родительского виджета:

PyQt QVBoxLayout - QLabel

Чтобы пропорционально распределить пространство для каждого виджета QLabel, используйте метод setStretchFactor() со следующим синтаксисом:

setStretchFactor(widget, factor)

Метод setStretchFactor() устанавливает коэффициент растяжения для виджета, чтобы растянуть его в макете. Поэтому вам нужно использовать метод setStretchFactor() после добавления дочерних виджетов в макет.

Следующая программа использует метод setStretchFactor() для установки коэффициентов растяжения для первого, второго и третьего виджетов QLabel как 1, 2 и 3:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons
        label_1 = QLabel('')
        label_1.setStyleSheet('QLabel{background-color:red}')

        label_2 = QLabel('')
        label_2.setStyleSheet('QLabel{background-color:green}')

        label_3 = QLabel('')
        label_3.setStyleSheet('QLabel{background-color:blue}')

        layout.addWidget(label_1)
        layout.addWidget(label_2)
        layout.addWidget(label_3)

        layout.setStretchFactor(label_1, 1)
        layout.setStretchFactor(label_2, 2)
        layout.setStretchFactor(label_3, 3)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

PyQt QVBoxLayout - Фактор растяжения макета

Из-за факторов растяжения второй виджет QLabel занимает в два раза больше места, чем первый, а третий виджет QLabel использует пространство в три раза больше, чем первый.

Установка интервалов между виджетами

По умолчанию QVBoxLayout устанавливает стандартное расстояние между виджетами. Чтобы изменить расстояние между виджетами, используйте метод setSpacing().

В следующем примере метод setSpacing() используется для установки нулевых интервалов между виджетами QLabel:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons
        label_1 = QLabel('')
        label_1.setStyleSheet('QLabel{background-color:red}')

        label_2 = QLabel('')
        label_2.setStyleSheet('QLabel{background-color:green}')

        label_3 = QLabel('')
        label_3.setStyleSheet('QLabel{background-color:blue}')

        layout.addWidget(label_1)
        layout.addWidget(label_2)
        layout.addWidget(label_3)

        layout.setSpacing(0)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Выход:

PyQt QVBoxLayout — настройка пространств

Установка полей контента

По умолчанию QVBoxLayout устанавливает определенные левые, верхние, правые и нижние поля для виджета. Чтобы изменить поля, используйте метод setContentsMargins():

setContentsMargins(self, left: int, top: int, right: int, bottom: int) -> None

Например, ниже метод setContentsMargins() используется для установки полей для виджетов QLabel на ноль:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setWindowTitle('PyQt QVBoxLayout')

        # create a layout
        layout = QVBoxLayout()
        self.setLayout(layout)

        # create buttons
        label_1 = QLabel('')
        label_1.setStyleSheet('QLabel{background-color:red}')

        label_2 = QLabel('')
        label_2.setStyleSheet('QLabel{background-color:green}')

        label_3 = QLabel('')
        label_3.setStyleSheet('QLabel{background-color:blue}')

        layout.addWidget(label_1)
        layout.addWidget(label_2)
        layout.addWidget(label_3)

        # set the contents margins
        layout.setContentsMargins(0, 0, 0, 0)

        # show the window
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

Выход:

PyQt QVBoxLayout — настройка полей содержимого

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *