Менеджер геометрии Tkinter Pack в Python
Tkinter использует менеджер геометрии для организации виджетов в окне. Tkinter поддерживает три менеджера геометрии:
- pack
- grid
- place
- Tkinter pack geometry manager
- Параметры Tkinter pack
- Side
- Пробелы для виджетов
- Expand
- Fill
- Внутренние отступы: ipadx и ipady
- Внешние отступы: padx и pady
- Anchor
- Использование пакета Tkinter для создания формы входа
Tkinter pack geometry manager
Менеджер геометрии pack организует виджеты в блоки перед их размещением в виджете-контейнере, который может быть главным окном или фреймом.
Менеджер геометрии пакета имеет множество опций для упорядочивания виджетов:
- Side
- Expand
- Fill
- ipadx, ipady
- padx, pady
- Anchor
Прежде чем углубляться в каждую опцию, вам необходимо понять координаты x и y окна:
Верхний левый угол окна — это начало координат с координатой(0,0). Координата x увеличивается слева направо, а координата y увеличивается сверху вниз.
Параметры Tkinter pack
Создадим простую программу, иллюстрирующую работу менеджера геометрии pack:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack() label2.pack() label3.pack() root.mainloop()
Программа имеет главное окно с тремя метками с красным, зеленым и синим фоном.
Чтобы использовать менеджер геометрии pack, вы вызываете pack() виджета. По умолчанию Tkinter pack размещает виджеты в одном направлении вертикально сверху вниз.
Side
Параметр side определяет направление виджетов в макете пакета.
Параметр side имеет четыре варианта:
- «top»: расположить виджеты сверху вниз по вертикали.
- «bottom»: расположить виджеты снизу вверх по вертикали.
- «left»: виджеты слева направо по горизонтали.
- «right»: справа налево по горизонтали.
По умолчанию установлено значение «top», что позволяет расположить виджет вертикально сверху вниз.
Помимо строковых констант вы можете использовать предопределенные константы, предоставляемые модулем Tkinter:
- tk.TOP
- tk.BOTTOM
- tk.LEFT
- tk.RIGHT
Обратите внимание, что мы импортировали модуль Tkinter как tk.
Следующая программа явно устанавливает «top», что позволяет расположить метки вертикально сверху вниз:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack(side=tk.TOP) label2.pack(side=tk.TOP) label3.pack(side=tk.TOP) root.mainloop()
При изменении side на tk.BOTTOM менеджер pack располагает метки снизу вверх по вертикали:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack(side=tk.BOTTOM) label2.pack(side=tk.BOTTOM) label3.pack(side=tk.BOTTOM) root.mainloop()
Выход:
tk.LEFT располагает метки слева направо:
tk.RIGHT располагает метки справа налево:
Пробелы для виджетов
В Tkinter есть два вида пробелов:
- Пробел, который может занимать виджет.
- Пробел, который будет занимать виджет.
По умолчанию виджет будет занимать только необходимое пространство для отображения своего содержимого. Однако виджет может занимать больше места.
Например, виджет Label будет иметь размер, равный размеру текста. Цвет фона показывает, что каждая метка имеет разную ширину, поскольку длина ее текста разная.
Expand
Параметр expand определяет, должен ли виджет расширяться, чтобы занять дополнительное пространство, выделенное контейнеру.
Если expand установлен на True, виджет будет расширяться, а если установлен на False, то нет. Параметр expand по умолчанию имеет значение False.
Параметр expand сильно зависит от параметра side. В следующей таблице показаны зависимости между параметрами side и expand, когда речь идет о пространстве виджета.
Side | Expand |
---|---|
Top (или Bottom) | Виджет может быть такой же ширины, как и контейнер, expand определит высоту виджета. |
Left (или Right) | Виджет может быть такой же высоты, как и контейнер, expand будет определять ширину виджета. |
Следующая программа размещает виджеты Label вертикально сверху вниз и устанавливает параметр expand первого виджета Label в значение True, а двух других виджетов Label в значение False:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack(side=tk.TOP, expand=True) label2.pack(side=tk.TOP, expand=False) label3.pack(side=tk.TOP, expand=False) root.mainloop()
Поскольку мы установили параметр expand первой метки в значение true, она занимает все вертикальное пространство и сдвигает два других виджета метки вниз:
Следующая программа размещает виджеты Label горизонтально слева направо и устанавливает параметр expand первого виджета Label в значение True, а двух других виджетов Label в значение False:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack(side=tk.LEFT, expand=True) label2.pack(side=tk.LEFT, expand=False) label3.pack(side=tk.LEFT, expand=False) root.mainloop()
Поскольку мы установили параметр expand первой метки в значение true, она занимает все горизонтальное пространство и сдвигает два других виджета метки вправо:
Если установить параметр expand трех виджетов Label на True, они будут занимать ровное горизонтальное пространство:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white') label1.pack(side=tk.LEFT, expand=True) label2.pack(side=tk.LEFT, expand=True) label3.pack(side=tk.LEFT, expand=True) root.mainloop()
Выход:
Fill
Параметр fill определяет, будет ли виджет занимать доступное пространство. Он принимает следующие значения: ‘x’, ‘y’, ‘both’ и ‘none’. По умолчанию — ‘none’.
Fill |
Эффект |
---|---|
‘none’ | Виджет не будет расширяться, чтобы заполнить дополнительное пространство. Он занимает только место, которое соответствует контенту. |
‘х’ | Виджет расширится по горизонтали, чтобы заполнить все дополнительное пространство по оси X. |
‘y’ | Виджет расширится по вертикали, чтобы заполнить все свободное пространство по оси Y. |
‘both’ | Будет расширяться как по горизонтали, так и по вертикали, заполняя все свободное пространство в обоих направлениях. |
Следующая программа иллюстрирует, как работает параметр fill:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white') label3 = tk.Label(master=root, text='Fill',bg='blue', fg='white') label4 = tk.Label(master=root, text='Demo',bg='purple', fg='white') label1.pack(side=tk.TOP, expand=True, fill=tk.X) label2.pack(side=tk.TOP, expand=True, fill=tk.Y) label3.pack(side=tk.TOP, expand=True, fill=tk.NONE) label4.pack(side=tk.TOP, expand=True, fill=tk.BOTH) root.mainloop()
Выход:
В этом примере мы размещаем виджеты Label вертикально сверху вниз. Расширения всех виджетов Label установлены на True.
- Первый виджет Label имеет значение заполнения tk.X, что позволяет ему заполнять дополнительные пространства вдоль оси x.
- Второй виджет Label имеет значение заполнения tk.Y, что позволяет ему заполнять дополнительные пространства вдоль оси Y.
- Третий виджет Label имеет значение заполнения tk.NONE, что означает, что он не расширяется для заполнения дополнительного пространства.
- Четвертый виджет Label имеет значение заполнения tk.BOTH, что позволяет ему занимать любое дополнительное пространство как в горизонтальном, так и в вертикальном направлении.
Внутренние отступы: ipadx и ipady
Параметры ipadx и ipady создают внутренние отступы для виджетов:
- ipadx создает отступы слева и справа или отступы вдоль оси x.
- ipady создает отступы сверху и снизу или отступы вдоль оси Y.
Например, следующая программа использует параметры ipadx и ipady для установки внутренних отступов каждого виджета Label:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Pack',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack',bg='green', fg='white') label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white') label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white') label1.pack(side=tk.LEFT) label2.pack(side=tk.LEFT, ipadx=40) label3.pack(side=tk.LEFT, ipady=40) label4.pack(side=tk.LEFT, ipadx=80, ipady=80) root.mainloop()
Выход:
Внешние отступы: padx и pady
Параметры padx и pady позволяют указать отступы, которые будут добавлены по горизонтали и вертикали соответственно:
- padx – представляет собой горизонтальный отступ, который добавляет пространство слева и справа от виджета.
- pady – представляет собой вертикальный отступ, который добавляет пространство над или под виджетом.
Следующий пример иллюстрирует, как использовать pady:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Pack',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack',bg='green', fg='white') label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white') label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white') label1.pack(side=tk.TOP, fill=tk.X, pady=10) label2.pack(side=tk.TOP, fill=tk.X, pady=20) label3.pack(side=tk.TOP, fill=tk.X ,pady=40) label4.pack(side=tk.TOP, fill=tk.X, pady=60) root.mainloop()
Выход:
Следующая программа иллюстрирует, как использовать padx:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Pack',bg='red',fg='white') label2 = tk.Label(master=root,text='Pack',bg='green', fg='white') label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white') label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white') label1.pack(side=tk.LEFT, fill=tk.X, padx=10) label2.pack(side=tk.LEFT, fill=tk.X, padx=20) label3.pack(side=tk.LEFT, fill=tk.X ,padx=40) label4.pack(side=tk.LEFT, fill=tk.X, padx=60) root.mainloop()
Выход:
Anchor
Параметр anchor позволяет прикрепить виджет к краю выделенного пространства. Он принимает одно из следующих значений:
Стик | Описание |
---|---|
‘n’ | Север или центр |
‘s’ | Юг или нижний центр |
‘e’ | Восток или правый центр |
‘w’ | Запад или левый центр |
‘nw’ | Северо-запад или верхний левый угол |
‘ne’ | Северо-восток или верхний правый угол |
‘se’ | Юго-Восток или нижний правый угол |
‘sw’ | Юго-запад или нижний левый угол |
‘center’ | Центр |
На следующем рисунке показаны варианты anchor:
Например, следующая программа показывает виджеты, использующие anchor E и W:
import tkinter as tk root = tk.Tk() root.title('Pack Demo') root.geometry("350x200") # box 1 box1 = tk.Label(root, text="Box 1", bg="green", fg="white") box1.pack(ipadx=20, ipady=20, anchor=tk.E, expand=True) # box 2 box2 = tk.Label(root, text="Box 2", bg="red", fg="white") box2.pack(ipadx=20, ipady=20, anchor=tk.W, expand=True) root.mainloop()
Выход:
Использование пакета Tkinter для создания формы входа
В следующем примере метод pack() используется для создания формы входа:
import tkinter as tk from tkinter import ttk root = tk.Tk() root.title('Login') root.geometry("350x220") fields = {} fields['username_label'] = ttk.Label(text='Username:') fields['username'] = ttk.Entry() fields['password_label'] = ttk.Label(text='Password:') fields['password'] = ttk.Entry(show="*") for field in fields.values(): field.pack(anchor=tk.W, padx=10, pady=5, fill=tk.X) ttk.Button(text='Login').pack(anchor=tk.W, padx=10, pady=5) root.mainloop()
Выход:
Как это работает.
- Сначала инициализируем словарь для хранения виджетов:
fields = {}
- Во-вторых, создайте виджеты «Label» и «Entry»:
fields['username_label'] = ttk.Label(text='Username:') fields['username'] = ttk.Entry() fields['password_label'] = ttk.Label(text='Password:') fields['password'] = ttk.Entry(show="*")
- В-третьих, пройдитесь по виджетам и упакуйте их:
for field in fields.values(): field.pack(anchor=tk.W, padx=10, pady=5, fill=tk.X)
- Наконец, добавьте кнопку входа:
ttk.Button(text='Login').pack(anchor=tk.W, padx=10, pady=5)