Графический интерфейс для программы на Python можно создать с помощью одной из специальных GUI библиотек:
- Tkinter
- wxPython
- PyQt
- PySide
- Kivy
- PyGTK
У каждой из этих библиотек есть свои преимущества и недостатки. Только одна из них, Tkinter, входит в стандартную поставку Python. Виджеты Tkinter не отличаются сногсшибательной стильностью – это ее единственный очевидный минус. Преимуществ у Tkinter гораздо больше, чем недостатков. Эта библиотека:
- Максимально проста в изучении и использовании.
- Имеет детальную и доступную документацию.
- Помимо базовых элементов интерфейса, содержит два мощных виджета – Text (многострочное текстовое поле с поддержкой форматирования) и Canvas («холст», на котором можно рисовать и отображать любые графические объекты).
- Включает в себя модуль ttk, который предоставляет в распоряжение разработчика набор дополнительных виджетов – Combobox, Notebook, Treeview, Progressbar, Scale и другие.
- Позволяет сделать интерфейс адаптивным.
- Отлично подходит для начинающих – поэтому на ней мы и сосредоточимся.
Создание окна приложения с Tkinter
Для создания простого окна приложения в Tkinter выполните следующие действия:
- Импортируйте модуль
import tkinter
. - Создайте новый объект
Tk
, который представляет собой главное окно приложения. - (Опционально) Задайте заголовок окна с помощью метода
title()
объектаTk
. - (Опционально) Установите размер окна с помощью метода
geometry()
объекта Tk. Методgeometry()
принимает строковый параметр в формате"ширинаxвысота"
. - Вызовите метод
mainloop()
объекта Tk, чтобы запустить основной цикл GUI приложения.
Вот пример кода, который создает простое окно размером 250 на 250 пикселей с заголовком «Мое приложение»:
import tkinter as tk
# Создайте новый объект Tk
root = tk.Tk()
# Задайте заголовок окна
root.title("Мое приложение")
# Установите размер окна
root.geometry("250x250")
# Запустите основной цикл
root.mainloop()
Позиционирование окна в центре экрана
Чтобы разместить окно Tkinter приложения в центре экрана, необходимо:
- Воспользоваться методами winfo_screenwidth() и winfo_screenheight() для получения ширины и высоты экрана соответственно.
- Передать в метод geometry() координаты x и y, равные половине ширины и высоты экрана за минусом половины ширины и высоты окна приложения.
Код будет выглядеть так:
import tkinter as tk
# Создаем окно
root = tk.Tk()
# Получаем ширину и высоту экрана
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Вычисляем координаты окна приложения
window_width = 500
window_height = 300
x = (screen_width // 2) - (window_width // 2)
y = (screen_height // 2) - (window_height // 2)
root.geometry(f"{window_width}x{window_height}+{x}+{y}")
# Запускаем программу
root.mainloop()
Теперь окно расположено точно в центре экрана:
Размещение элементов интерфейса в Tkinter
Элементы интерфейса в Tkinter называются виджетами. Существует три основных способа расположения виджетов на поверхности окна: pack(), place() и grid(). Каждый из этих методов имеет свои преимущества и недостатки, и выбор оптимального способа зависит от конкретной ситуации.
pack() – упорядочивает виджеты по горизонтали или вертикали. Он прост в использовании, не требует дополнительных параметров (указания отступов, конкретной позиции). Подходит для создания простых интерфейсов. Недостаток – с помощью pack() проблематично реализовать сложную компоновку, например, сетку или перекрывание виджетов: для этого нужно комбинировать метод с place().
import tkinter as tk
root = tk.Tk()
label1 = tk.Label(root, text="Это пример использования pack()")
label1.pack()
button1 = tk.Button(root, text="Нажми!")
button1.pack()
root.mainloop()
place() – позволяет задать точное положение и размер каждого виджета в окне. Его используют, когда необходимо точно расположить виджеты или создать перекрывающиеся элементы интерфейса. Недостаток – при изменении размеров окна или содержимого виджетов трудно сохранить расположение элементов.
import tkinter as tk
root = tk.Tk()
label1 = tk.Label(root, text="Это пример использования place()")
label1.place(x=5, y=50)
button1 = tk.Button(root, text="Нажми кнопку")
button1.place(x=50, y=100)
root.mainloop()
grid() – упорядочивает виджеты в сетку из рядов и столбцов. Самый гибкий и мощный, позволяет создавать сложные интерфейсы, состоящие из виджетов разных размеров. Сложнее в использовании, чем pack(), поскольку требует больше кода для компоновки виджетов.
import tkinter as tk
root = tk.Tk()
root.title("Пример grid()")
root.geometry("250x250")
frame = tk.Frame(root)
frame.pack(expand=True)
label1 = tk.Label(frame, text="Имя:")
label1.grid(row=0, column=0)
entry1 = tk.Entry(frame)
entry1.grid(row=0, column=1)
label2 = tk.Label(frame, text="Email:")
label2.grid(row=1, column=0)
entry2 = tk.Entry(frame)
entry2.grid(row=1, column=1)
button1 = tk.Button(frame, text="Отправить")
button1.grid(row=2, column=1)
root.update_idletasks()
width = root.winfo_width()
height = root.winfo_height()
x = (root.winfo_screenwidth() // 2) - (width // 2)
y = (root.winfo_screenheight() // 2) - (height // 2)
root.geometry('{}x{}+{}+{}'.format(width, height, x, y))
root.mainloop()

В целом, pack() хорошо подходит для простых интерфейсов, place() – для более сложных, а grid() используют для создания сложных интерфейсов, которым нужна адаптивность, особое позиционирование или растягивание виджетов на несколько строк / столбцов.
Связывание виджетов с функциями
Чтобы при нажатии кнопки выполнялось какое-то действие, нужно связать кнопку с определенной функцией. Чаще всего для этого используются методы command() и bind(), но при необходимости к виджетам Tkinter можно привязывать выполнение анонимных и частично примененных функций. Проиллюстрируем примерами.
Метод command() используется для прямого связывания функции с нажатием кнопки:
import tkinter as tk
root = tk.Tk()
def say_hello():
print("Привет!")
button1 = tk.Button(root, text="Поздоровайся", command=say_hello)
button1.pack()
root.mainloop()

Метод bind(), по сравнению с command(), отличается большей гибкостью: его можно использовать для связывания функции с любым событием, происходящим в виджете – с нажатием кнопки, движением мыши, нажатием клавиши, изменением размера окна и так далее:
import tkinter as tk
root = tk.Tk()
def say_hello(event=None):
print("Привет от метода bind()")
button1 = tk.Button(root, text="Нажми кнопку")
button1.bind("<Button-1>", say_hello)
button1.pack()
root.mainloop()

Назначение кнопке анонимной функции:
import tkinter as tk
root = tk.Tk()
button1 = tk.Button(root, text="Нажми!", command=lambda: print("Привет от анонимной функции!"))
button1.pack()
root.mainloop()

Связывание кнопки с частично примененной функцией:
import tkinter as tk
from functools import partial
root = tk.Tk()
def say_hello(name):
print(f"Привет, {name}!")
button1 = tk.Button(root, text="Нажми эту кнопку", command=partial(say_hello, "пользователь"))
button1.pack()
root.mainloop()

Отлично! Вы освоили все основы для создания интерактивных GUI-приложений на Tkinter.
Вы умеете создавать окна, размещать на них виджеты с помощью pack
, place
и grid
, и делать их интерактивными, связывая с функциями. У вас есть все базовые инструменты.
Теперь пора переходить от теории к созданию полноценных, функциональных приложений. В полной версии урока вас ждут 10 практических проектов, в которых вы:
- Познакомитесь с десятком новых виджетов: от
Progressbar
иCombobox
доTreeview
. - Научитесь структурировать код сложных приложений (таких как калькулятор) с помощью классов.
- Создадите 10 готовых GUI-программ, которые можно использовать как основу для собственных проектов.
Какие трудности у вас возникают при создании GUI на Python?