PyQt QVBoxLayout в Python для вертикального расположения виджетов
PyQt QVBoxLayout делит родительский виджет на вертикальные блоки и размещает дочерние виджеты последовательно сверху вниз в Python.
- Что такое PyQt QVBoxLayout
- Выравнивания
- Выровнять по низу
- Выровнять по верху
- Выравнивание по центру
- Установка коэффициентов растяжения макета
- Установка интервалов между виджетами
- Установка полей контента
Что такое 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:
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 горизонтально, а не вертикально.
Это означает, что при увеличении ширины родительского виджета ширина всех кнопок также увеличивается:
Однако, когда вы увеличиваете высоту родительского виджета, высота кнопок не меняется. Что еще более важно, QVBoxLayout равномерно распределяет пространство родительского виджета между каждой кнопкой:
Если в родительском виджете достаточно места для дочерних виджетов, вы можете выровнять их внутри родительского с помощью вертикальных разделителей.
Выровнять по низу
Чтобы переместить кнопки в нижнюю часть родительского виджета, добавьте вертикальный разделитель в начале макета с помощью метода addStretch() объекта 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() после добавления кнопок в макет:
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())
Выравнивание по центру
Чтобы выровнять кнопки по центру родительского виджета, добавьте вертикальный разделитель в начале и в конце макета, как показано ниже:
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. Например, следующий код добавляет вертикальный разделитель между второй и третьей кнопками:
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 растягиваются как по вертикали, так и по горизонтали при изменении размера родительского виджета:
Чтобы пропорционально распределить пространство для каждого виджета 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())
Из-за факторов растяжения второй виджет 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())
Выход:
Установка полей контента
По умолчанию 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())
Выход: