Управление макетом в PyQt5 [Урок №4]
 9 марта 2015 г.
 9 марта 2015 г. Archy
 Archy Просмотров: 38807
 Просмотров: 38807 RSS
 RSS 1
  1 Изучение PyQt5
 Изучение PyQt5 PyQt, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit, QWidget, примеры PyQt
 PyQt, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit, QWidget, примеры PyQtСущественная сторона в программировании графических приложений – управление макетом. Управление макетом – это способ, которым мы размещаем виджеты в окне приложения. Управление может быть выполнена двумя основными путями. Мы можем использовать абсолютное позиционирование или классы макета.
Абсолютное позиционирование
Программист указывает позицию и размер каждого виджета в пикселях. При использовании абсолютного позиционирования, мы должны понимать следующие ограничения:
- Размер и позиция виджета не меняются, если мы меняем размер окна
- Приложения могут выглядеть по-разному на разных платформах
- Изменение шрифтов в нашем приложении может испортить макет
- Если мы решаем изменить наш макет, мы должны полностью переделать его, что утомительно и время-затратно.
Следующий пример размещает виджеты в абсолютных координатах.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
 
class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        lbl1 = QLabel('Zetcode', self)
        lbl1.move(15, 10)
        lbl2 = QLabel('tutorials', self)
        lbl2.move(35, 40)
        
        lbl3 = QLabel('for programmers', self)
        lbl3.move(55, 70)        
        
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Absolute')    
        self.show()
         
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
Мы используем метод move(), чтобы разместить наши виджеты. В этом случае ими являются метки. Мы размещаем их путём предоставления координат x и y. Начало координатной системы – левый верхний угол. Значения x возрастают слева направо. Значения y растут сверху вниз.
lbl1 = QLabel('Zetcode', self)
lbl1.move(15, 10)Виджет метки расположен в x=15 и y=10.

Рисунок: абсолютное позиционирование
Блочный макет
Управление макетом с классами макета является более гибким и практичным. Это предпочтительный путь размещения виджетов в окне. QHBoxLayout и QVBoxLayout – это основные классы макета, которые выстраивают виджеты горизонтально или вертикально.
Представьте, что мы хотим разместить две кнопки в правом нижнем углу. Чтобы создать такой макет, мы будем использовать один горизонтальный и один вертикальный блок. Чтобы создать необходимое свободное пространство, мы добавим показатель растяжения.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QApplication)
class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        okButton = QPushButton("OK")
        cancelButton = QPushButton("Cancel")
        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)
        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)    
        
        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Buttons')    
        self.show()
         
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
Пример размещает две кнопки в нижнем правом углу окна. Они остаются там, когда мы изменяем размер окна приложения. Мы можем использовать и HBoxLayout, и QVBoxLayout.
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
Здесь мы создаём две кнопки.
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)Мы создаём макет горизонтального блока, добавляем показатель растяжения и обе кнопки. Растяжение добавляет растянутое свободное пространство перед двумя кнопками. Это прижмёт их к правому краю окна.
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)Чтобы создать необходимый макет, мы поставим горизонтальный макет в вертикальный. Показатель растяжения в вертикальном блоке прижмёт горизонтальный блок с кнопками к нижней части окна.
self.setLayout(vbox)Наконец, мы устанавливаем главный макет окна.

Рисунок: Кнопки
QGridLayout
Самый универсальный класс макета – это сеточный макет. Этот макет делит пространство на строки и столбцы. Чтобы создать сеточный макет, мы используем класс QGridLayout.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout, QPushButton, QApplication)
 
class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)
 
        names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '=', '+']
        positions = [(i,j) for i in range(5) for j in range(4)]
        
        for position, name in zip(positions, names):
            if name == '':
                continue
            button = QPushButton(name)
            grid.addWidget(button, *position)
            
        self.move(300, 150)
        self.setWindowTitle('Calculator')
        self.show()
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
В нашем примере, мы создаём сетку из кнопок. Чтобы заполнить один промежуток, мы добавляем один виджет QLabel.
grid = QGridLayout()
self.setLayout(grid)Создаётся экземпляр QGridLayout, он назначается как макет окна приложения.
names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '=', '+']Это метки, используемые в дальнейшем для кнопок.
positions = [(i,j) for i in range(5) for j in range(4)]Мы создаём список позиций для сетки.
for position, name in zip(positions, names):
    if name == '':
        continue
    button = QPushButton(name)
    grid.addWidget(button, *position)Используя метод addWidget, создаются и добавляются кнопки к макету.

Рисунок: Каркас калькулятора
Обзорный пример
Виджеты могут охватывать несколько столбцов и строк в сетке. В следующем примере мы продемонстрируем это.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)
 
class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        title = QLabel('Title')
        author = QLabel('Author')
        review = QLabel('Review')
        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        reviewEdit = QTextEdit()
        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(title, 1, 0)
        grid.addWidget(titleEdit, 1, 1)
        grid.addWidget(author, 2, 0)
        grid.addWidget(authorEdit, 2, 1)
        grid.addWidget(review, 3, 0)
        grid.addWidget(reviewEdit, 3, 1, 5, 1)
        
        self.setLayout(grid) 
        
        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Review')    
        self.show()
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())Купить подписчиков в группу Телеграмма от 1,2 рублей можно только на https://doctorsmm.com/. На данном сайте представлен широкий спектр услуг по продвижению в данной социальной сети. Здесь Вы сможете найти качественные аккаунты с высоким скоростным режимом (до 1000 ед. в сутки) и большими оптовыми скидками. Все предложения действуют ограниченное время, поэтому торопитесь сделать самый выгодный заказ!
Мы создаём окно, в котором мы имеем три метки, две строки правки и один виджет редактирования текста. Макет сделан с помощью QGridLayout.
grid = QGridLayout()
grid.setSpacing(10)Мы создаём сеточный макет и устанавливаем промежуток между виджетами.
grid.addWidget(reviewEdit, 3, 1, 5, 1)Если мы добавляем виджет к сетке, мы можем обеспечить объединение строк и столбцов виджета. В нашем примере, мы делаем так, что виджет reviewEdit объединяет 5 строк.

Рисунок: Обзорный пример
Эта часть руководства по PyQt5 была посвящена управлению макетом.
![Управление макетом в PyQt5 [Урок №4] Управление макетом в PyQt5 [Урок №4]](http://python-3.ru/uploads/layout-management-in-pyqt5.png)

Если у вас возникнет резонный вопрос, почему не работает gridLayout в mainwindow, а в QWidget нельзя создать меню и панель инструментов, то вот решение:
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
widget = QWidget(self)
self.setCentralWidget(widget)
grid = QGridLayout(widget)
...
grid.addWidget(Что угодно)
Мы создаем экземпляр mainwindow, а уже в нем - объект QWidget, который назначаем центральным окном.
Меню и тулбар спокойно создаются, как и раньше в самом mainwindow
...
menubar = self.menuBar()
...
self.toolbar = self.addToolBar(Что угодно)