</>
Topic 3 of 6

Course materials are currently available in Russian only.

Раскладка

Виджеты сами по себе в окне не появляются: их расставляет менеджер геометрии. В Tkinter их три — pack, grid и place.

pack — друг за другом

pack складывает виджеты в стопку: по умолчанию сверху вниз.

tk.Label(root, text="Заголовок").pack(pady=10)
tk.Entry(root).pack(fill="x", padx=10)          # растянуть по ширине
tk.Button(root, text="OK").pack(side="right")   # прижать вправо
  • side — к какой стороне прижимать: "top" (по умолчанию), "bottom", "left", "right";
  • fill="x", "y" или "both" — растянуть по оси;
  • expand=True — забрать свободное место при увеличении окна;
  • padx, pady — внешние отступы.

grid — таблица

grid кладёт виджеты в ячейки таблицы. Строки и столбцы нумеруются с нуля:

tk.Label(root, text="Имя").grid(row=0, column=0, sticky="w")
tk.Entry(root).grid(row=0, column=1)
tk.Label(root, text="Пароль").grid(row=1, column=0, sticky="w")
tk.Entry(root, show="*").grid(row=1, column=1)
tk.Button(root, text="Войти").grid(row=2, column=0, columnspan=2, sticky="ew")
  • columnspan, rowspan — сколько ячеек занимает виджет;
  • sticky — к каким краям ячейки прижать: "n", "s", "e", "w" и их сочетания; "nsew" — растянуть на всю ячейку;
  • grid_columnconfigure(c, weight=1) — столбец растягивается вместе с окном; minsize — минимальная ширина.

Когда кнопки создаются в цикле, номер кнопки i легко превратить в ячейку: строка i // cols, столбец i % cols.

Frame — рамка-группа

В одном контейнере нельзя смешивать pack и grid. Зато можно положить через pack рамку Frame, а внутри неё раскладывать через grid:

screen = tk.Label(root, text="0")
screen.pack(fill="x")
pad = tk.Frame(root)
pad.pack()
for i, key in enumerate("789456123"):
    tk.Button(pad, text=key, width=4).grid(row=i // 3, column=i % 3)

place — точные координаты

place(x=20, y=40) ставит виджет в точку в пикселях, place(relx=0.5, rely=0.5, anchor="center") — в долях размера окна (здесь — ровно в центр). Используют редко: при изменении окна такие виджеты сами не подстраиваются.

Кнопки из цикла и lambda

У кнопок, созданных в цикле, command часто пишут через lambda с параметром по умолчанию:

for i in range(9):
    tk.Button(root, command=lambda i=i: play(i)).grid(row=i // 3, column=i % 3)

i=i запоминает текущее значение i. Без него все кнопки вызвали бы play(8) — последнее значение переменной.

Итог

  • pack — стопкой (side, fill, expand), grid — таблицей (row, column, columnspan, sticky), place — координатами;
  • один менеджер на контейнер, группы — через Frame;
  • номер в сетке: (i // cols, i % cols);
  • lambda i=i: ... для кнопок из цикла.