Шаг 16.
Библиотека Tkinter. Размещение компонентов в контейнерах. Диспетчеры компоновки. Grid: выстраивание компонентов по сетке
На этом шаге мы рассмотрим назначение, его параметры и пример использования.
Диспетчер компоновки Grid размещает компоненты в ячейках воображаемой сетки, накладываемой на контейнер. Компонент также может занимать сразу несколько столбцов или строк такой
сетки - это может пригодиться, если требуется вывести в контейнере очень большой элемент управления. Если в одной и той же ячейке окажутся несколько компонентов, они будут наложены друг на друга.
В случае применения этого диспетчера компоновки нам также не придется задавать размеры контейнера - он сам примет такие размеры, чтобы вместить все свое содержимое.
Вывод компонентов посредством диспетчера компоновки Grid выполняется вызовом метода grid([<Параметры>]), поддерживаемого всеми компонентами. Вот параметры, которые мы можем использовать в этом методе:
- row - задает номер строки, в которую будет помещен текущий компонент, в виде целого числа. Нумерация строк начинается с 0. Если параметр не указан, компонент будет помещен в
строку, следующую за той, в которую был вставлен предыдущий компонент, или в первую строку (с номером 0), если это первый компонент, вставляемый в контейнер;
- column - задает номер столбца, в который будет помещен текущий компонент, в виде целого числа. Нумерация столбцов начинается с 0. Если параметр не указан, компонент будет помещен в первый столбец (с номером 0):
lblName.grid(row=0, column=0)
entName.grid(row=0, column=1)
btnOK.grid(row=1, column=1)
При этом надпись lblName будет помещена в ячейку, образованную первой строкой и первым столбцом, поле ввода entName - в ячейку, образованную первой строкой и вторым столбцом,
а кнопка btnOK - в ячейку, находящуюся на пересечении второй строки и второго столбца. Ячейка на пересечении второй строки и первого столбца останется пустой;
- columnspan - задает количество столбцов, которые займет текущий компонент. Значение по умолчанию - 1 (то есть компонент занимает всего один столбец):
entName.grid(row=0, column=1, columnspan=2)
Здесь мы растягиваем поле ввода на два столбца: второй и третий;
- rowspan - задает количество строк, которые займет текущий компонент. Значение по умолчанию - 1 (то есть компонент занимает всего одну строку);
- sticky - управляет выравниванием текущего компонента в пространстве контейнера, отведенном под его размещение. Значение параметра должно представлять собой строку,
содержащую следующие символы:
- "w" - левая сторона компонента прижимается к левой стороне свободного пространства;
- "n" - верхняя сторона компонента прижимается к верхней стороне свободного пространства;
- "е" - правая сторона компонента прижимается к правой стороне свободного пространства;
- "s" - нижняя сторона компонента прижимается к нижней стороне свободного пространства.
Эти символы для удобства читаемости могут быть разделены запятыми и пробелами:
btnAdd.grid(sticky="e")
btnOK.grid(sticky="n, s")
При этом кнопка btnAdd правой стороной прижмется к правой границе выделенного под него пространства. А кнопка btnOK верхней границей прижмется к верхней границе пространства,
а своей нижней стороной - к его нижней стороне, растянувшись, таким образом, по вертикали на все выделенное под нее пространство контейнера.
Если в качестве значения параметра указана пустая строка, компонент будет расположен в середине свободного пространства.
Параметр sticky имеет смысл указывать только в том случае, если размеры компонента меньше размеров выделенного под него пространства;
- ipadx - задает величину отступа между границами компонента и его содержимым по горизонтали в виде дистанции. Значение по умолчанию - 0 (отступы отсутствуют);
- ipady - задает величину отступа между границами компонента и его содержимым по вертикали в виде дистанции. Значение по умолчанию - 0 (отступы отсутствуют):
btnOK.grid(ipadx=3, ipady=3)
Здесь мы указываем отступы по горизонтали и вертикали равными 3-м пикселям;
- padx - задает величину отступа между границами соседних компонентов и границами текущего компонента и контейнера, в котором он находится, по горизонтали в виде дистанции.
Может быть задана в виде:
- обычного значения - указывает отступы и слева, и справа;
- списка из двух элементов: значение первого элемента укажет отступ слева, второго - справа.
Значение по умолчанию - 0 (отступы отсутствуют);
- pady - задает величину отступа между границами соседних компонентов и границами текущего компонента и контейнера, в котором он находится, по вертикали в виде дистанции. Может
быть задана в виде:
- обычного значения - указывает отступы и сверху, и снизу;
- списка из двух элементов: значение первого элемента укажет отступ сверху, второго - снизу.
Значение по умолчанию - 0 (отступы отсутствуют):
btnOK.grid(padx=5, pady=5)
Здесь мы указываем отступы по горизонтали и вертикали равными пяти пикселям;
- in_ - задает контейнер, в который будет помещен текущий компонент. Если параметр не указан, компонент будет помещен в его родитель, заданный в первом параметре конструктора класса компонента при его создании.
Для настройки параметров строк воображаемой сетки, по которой выстраиваются компоненты, применяется метод:
grid_rowconfigure(<Номер строки>, <Параметры>) ,
а для задания параметров столбцов - аналогичный метод:
grid_columnconfigure(<Номер столбца>, <Параметры>)
Оба этих метода поддерживаются всеми компонентами. Первым параметром в них указывается номер настраиваемой строки/столбца, а остальные доступные параметры таковы:
- minsize - задает минимальную высоту строки (или ширину столбца) в виде целого числа в пикселях. Если параметр не указан, строка/столбец может иметь любую высоту (ширину);
- pad - указывает величину дополнительных отступов сверху и снизу у самой высокой строки (или слева и справа у самого широкого столбца) в виде целого числа в пикселях. Значение по
умолчанию - 0 (дополнительные отступы отсутствуют);
- weight - управляет растягиванием строки/столбца. Если значение параметра представляет собой ненулевое целое число, строка/столбец будет растягиваться, чтобы занять все оставшееся
в окне свободное пространство. При этом значения этого параметра у всех таких строк/столбцов будет сложено, величина свободного пространства разделена на полученную сумму, и каждая строка/столбец примет
высоту/ширину, равную умножением полученного в результате деления частного на значение ее/его параметра weight.
Если значение этого параметра равно 0 (это, кстати, его значение по умолчанию), строка/столбец не будет растягиваться;
- uniform - служит для объединения строк/столбцов в группы. Такая группа включает все строки/столбцы, у которых для этого параметра задано одно и то же значение. Строки/столбцы,
входящие в группу, в любом случае будут иметь одинаковую высоту/ширину:
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 и поддерживаются всеми компонентами:
- grid_forget () - удаляет текущий компонент из контейнера;
- grid_remove () - то же самое, что и grid_forget(), но параметры, указанные в методе grid() при размещении текущего компонента в контейнере, сохраняются, и
впоследствии этот компонент можно вновь поместить в контейнер вызовом метода grid() без параметров;
- grid_slaves([column=None] [,] [row=None]) - возвращает список компонентов, находящихся:
- во всех ячейках контейнера - если был вызван без параметров;
- во всех ячейках столбца, чей номер был указан в параметре column;
- во всех ячейках строки, чей номер был указан в параметре row;
- в ячейке, расположенной на пересечении столбца и строки, чьи номера были указаны в параметрах column и row.
Этот метод вызывается у контейнера, сведения о компонентах которого нужно получить (с учетом параметров, заданных в приведенной выше программе):
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>]
- grid_info () - возвращает все параметры, заданные при размещении текущего компонента, в виде словаря. Ключи элементов этого словаря соответствуют названиям параметров, а их
значения - и есть значения этих параметров:
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'}
- grid_bbox ([<Столбец 1>, <Строка 1>[, <Столбец 2>, <Строка 2>]]) - возвращает координаты и размеры воображаемого прямоугольника, охватывающего:
- весь контейнер - если метод вызван без параметров;
- одну ячейку, расположенную на пересечении столбца и строки с указанными номерами, - если метод вызван с двумя параметрами;
- прямоугольный фрагмент, чья левая верхняя ячейка расположена на пересечении столбца и строки с номерами, заданными в первых двух параметрах, а правая нижняя ячейка образуется столбцом и строкой с номерами из
двух последних параметров, - если метод вызван с четырьмя параметрами.
Этот метод вызывается у контейнера, сведения о координатах и размерах которого нужно получить.
Возвращаемое значение представляет собой кортеж из четырех значений: горизонтальной и вертикальной координат левого верхнего угла прямоугольника, его ширины и высоты - все эти значения заданы
целыми числами и исчисляются в пикселях:
root = tkinter.Tk()
app = Application(master=root)
app.update() # Принудительная отрисовка окна
print(app.grid_bbox()) # Весь контейнер
root.mainloop()
Результат:
Обратите внимание, что в отличие от предыдущих шагов, где мы размещали функцию print(), например, в фунции create_widgets(), здесь же мы ее помещаем после конструкции
вызова метода update() объекта приложения. Дело в том, что вычисление координат возможно только после прорисовки виджетов на экране. Нужно либо дождыться запуска mainloop(),
либо принудительно перерисовать окно методом update(), что продемонстрировано в примере. В примерах ниже этого пункта использовано такое же расположение функции print();
это можно определить поиспользованию имени app вместо self.
print(app.grid_bbox(0, 0)) # Первая ячейка первой строки
Результат:
print(app.grid_bbox(0, 0, 0, 1)) # Фрагмент, содержащий обе ячейки
# первой строки
Результат:
- grid_location (<Горизонтальная координата>, <Вертикальная координата>) - возвращает местоположение ячейки текущего контейнера, на которой расположена точка
с указанными координатами. Координаты задаются относительно контейнера в виде целых чисел в пикселях. Результат возвращается в виде кортежа из двух целочисленных элементов: номера столбца и номера строки:
print(self.grid_location(100, 50))
Результат:
- grid_size() - возвращает кортеж с двумя целочисленными элементами: количеством столбцов и количеством строк в текущем контейнере:
Результат:
На следующем шаге мы рассмотрим использование вложенных контейнеров.
Предыдущий шаг
Содержание
Следующий шаг