На этом шаге мы рассмотрим назначение, его параметры и пример использования.
Диспетчер компоновки Grid размещает компоненты в ячейках воображаемой сетки, накладываемой на контейнер. Компонент также может занимать сразу несколько столбцов или строк такой сетки - это может пригодиться, если требуется вывести в контейнере очень большой элемент управления. Если в одной и той же ячейке окажутся несколько компонентов, они будут наложены друг на друга.
В случае применения этого диспетчера компоновки нам также не придется задавать размеры контейнера - он сам примет такие размеры, чтобы вместить все свое содержимое.
Вывод компонентов посредством диспетчера компоновки Grid выполняется вызовом метода grid([<Параметры>]), поддерживаемого всеми компонентами. Вот параметры, которые мы можем использовать в этом методе:
lblName.grid(row=0, column=0) entName.grid(row=0, column=1) btnOK.grid(row=1, column=1)
При этом надпись lblName будет помещена в ячейку, образованную первой строкой и первым столбцом, поле ввода entName - в ячейку, образованную первой строкой и вторым столбцом, а кнопка btnOK - в ячейку, находящуюся на пересечении второй строки и второго столбца. Ячейка на пересечении второй строки и первого столбца останется пустой;
entName.grid(row=0, column=1, columnspan=2)
Здесь мы растягиваем поле ввода на два столбца: второй и третий;
Эти символы для удобства читаемости могут быть разделены запятыми и пробелами:
btnAdd.grid(sticky="e") btnOK.grid(sticky="n, s")
При этом кнопка btnAdd правой стороной прижмется к правой границе выделенного под него пространства. А кнопка btnOK верхней границей прижмется к верхней границе пространства, а своей нижней стороной - к его нижней стороне, растянувшись, таким образом, по вертикали на все выделенное под нее пространство контейнера.
Если в качестве значения параметра указана пустая строка, компонент будет расположен в середине свободного пространства.
Параметр sticky имеет смысл указывать только в том случае, если размеры компонента меньше размеров выделенного под него пространства;
btnOK.grid(ipadx=3, ipady=3)
Здесь мы указываем отступы по горизонтали и вертикали равными 3-м пикселям;
Значение по умолчанию - 0 (отступы отсутствуют);
Значение по умолчанию - 0 (отступы отсутствуют):
btnOK.grid(padx=5, pady=5)
Здесь мы указываем отступы по горизонтали и вертикали равными пяти пикселям;
Для настройки параметров строк воображаемой сетки, по которой выстраиваются компоненты, применяется метод:
grid_rowconfigure(<Номер строки>, <Параметры>) ,
grid_columnconfigure(<Номер столбца>, <Параметры>)
Оба этих метода поддерживаются всеми компонентами. Первым параметром в них указывается номер настраиваемой строки/столбца, а остальные доступные параметры таковы:
Если значение этого параметра равно 0 (это, кстати, его значение по умолчанию), строка/столбец не будет растягиваться;
self.grid_rowconfigure(0, minsize=50, pad=4) self.grid_rowconfigure(1, weight=l) self.grid_rowconfigure(2, weight=3) self.column_configure(0, uniform="group1") self.column_configure(1, uniform="group1")
В результате первая строка сетки получит минимальную высоту в 50 пикселей и отступы сверху и снизу в 4 пикселя. Вторая и третья строки будут растягиваться: вторая строка займет 1/4 свободного пространства, а третья - 3/4. Первый и второй столбцы объединены в группу, вследствие чего всегда будут иметь одинаковую ширину.
Если значение параметра uniform - пустая строка (значение по умолчанию), строка/столбец не входит ни в какую группу.
Текст приведенного ниже примера содержит код приложения, аналогичного приложению, код которого был представлен на предыдущем шаге. Интерфейс этого приложения создан с применением диспетчера компоновки Grid. При любом изменении ширины окна поле ввода будет занимать 2/3 от его ширины, а кнопка Вывести значение - 1/3. Кнопка Выход же в любом случае будет находиться в правом нижнем углу окна.
import tkinter import tkinter.ttk class Application(tkinter.ttk.Frame): def __init__(self, master=None): super().__init__(master) self.pack(fill="both", padx=4, pady=4) self.create_widgets() self.master.title("Grid") # Указываем у окна возможность изменения только ширины self.master.resizable(True, False) def create_widgets(self): entValue = tkinter.ttk.Entry(self) entValue.grid(sticky="w, e") btnShow = tkinter.ttk.Button(self, text="Вывести значение") btnShow.grid(row=0, column=1, sticky="w, e") btnExit = tkinter.ttk.Button(self, text="Выход") btnExit.grid(column=1, sticky="e, s") self.grid_rowconfigure(1, pad=5) self.grid_columnconfigure(0, minsize=100, weight=2, pad=5) self.grid_columnconfigure(1, weight=1, pad=5) root = tkinter.Tk() app = Application(master=root) root.mainloop()
Результат работы приложения приведен на рисунке 1.

Рис.1. Результат работы приложения
Осталось рассмотреть дополнительные методы, которые могут пригодиться при работе с диспетчером компоновки Grid и поддерживаются всеми компонентами:
Этот метод вызывается у контейнера, сведения о компонентах которого нужно получить (с учетом параметров, заданных в приведенной выше программе):
print(self.grid_slaves())
[<tkinter.ttk.Button object at 0x0233E430>,
<tkinter.ttk.Button object at 0x0233E410>,
<tkinter.ttk.Entry object at 0x0233E550>]
print(self.grid_slaves(column=1))
[<tkinter.ttk.Button object at 0x0203E430>,
<tkinter.ttk.Button object at 0x0203E410>]
print(self.grid_slaves(column=1, row=1))
[<tkinter.ttk.Button object at 0x0215E430>]
print(btnExit.grid_info())
{'ipadx': 0, 'row': 1, 'rowspan': 1,
in': <__main__.Application object at 0x01FBE390>, 'pady': 0,
'padx': 0, 'column': 1, 'ipady': 0, 'columnspan': 1, 'sticky': 'es'}
Этот метод вызывается у контейнера, сведения о координатах и размерах которого нужно получить.
Возвращаемое значение представляет собой кортеж из четырех значений: горизонтальной и вертикальной координат левого верхнего угла прямоугольника, его ширины и высоты - все эти значения заданы целыми числами и исчисляются в пикселях:
root = tkinter.Tk() app = Application(master=root) app.update() # Принудительная отрисовка окна print(app.grid_bbox()) # Весь контейнер root.mainloop()
(0, 0, 246, 55)
Обратите внимание, что в отличие от предыдущих шагов, где мы размещали функцию print(), например, в фунции create_widgets(), здесь же мы ее помещаем после конструкции
вызова метода update() объекта приложения. Дело в том, что вычисление координат возможно только после прорисовки виджетов на экране. Нужно либо дождыться запуска mainloop(),
либо принудительно перерисовать окно методом update(), что продемонстрировано в примере. В примерах ниже этого пункта использовано такое же расположение функции print();
это можно определить поиспользованию имени app вместо self.
print(app.grid_bbox(0, 0)) # Первая ячейка первой строки
(0, 0, 131, 25)
print(app.grid_bbox(0, 0, 0, 1)) # Фрагмент, содержащий обе ячейки # первой строки
(0, 0, 131, 55)
print(self.grid_location(100, 50))
(0, 1)
print(self.grid_size())
(2, 2)
На следующем шаге мы рассмотрим использование вложенных контейнеров.