Первая программа с графическим интерфейсом на Tkinter
Первая программа на Tkinter занимает меньше десяти строк: окно, надпись и кнопка. В этом уроке шаг за шагом собирается небольшое оконное приложение на Python с обработчиком нажатия и полем ввода, а также разобраны способы размещения виджетов и ошибки, на которых чаще всего спотыкаются новички.

Содержание статьи
Проверка установки tkinter
Tkinter входит в стандартную библиотеку Python и использует набор Tcl/Tk. В официальных установщиках для Windows и macOS он включен по умолчанию. Проверить, что все работает, можно одной командой в терминале:
python -m tkinterДолжно открыться маленькое тестовое окно с версией Tk и двумя кнопками. Если появилась ошибка ModuleNotFoundError: No module named 'tkinter', модуль придется доустановить:
- Windows: запустите установщик Python с python.org, выберите Modify и отметьте пункт tcl/tk and IDLE. Команда
pip install tkне поможет, пакет с таким именем на PyPI к tkinter отношения не имеет. - Ubuntu и Debian:
sudo apt install python3-tk. - Fedora:
sudo dnf install python3-tkinter. - macOS с Python из Homebrew:
brew install python-tk.
Внутри программы модуль принято импортировать с коротким псевдонимом: import tkinter as tk. Так видно, какие имена пришли из библиотеки, и не засоряется пространство имен.
Минимальная программа с пустым окном
Любое приложение начинается с главного окна и заканчивается запуском цикла обработки событий.
import tkinter as tk
root = tk.Tk()
root.title("Мое первое приложение")
root.geometry("400x300")
root.mainloop()Что делает каждая строка:
tk.Tk()создает главное окно. В программе оно должно быть одно, дополнительные окна делаются черезtk.Toplevel().title()задает текст в заголовке окна.geometry("400x300")устанавливает ширину и высоту в пикселях. Можно сразу указать положение на экране:"400x300+100+50".mainloop()запускает бесконечный цикл, который ждет нажатий, движений мыши и перерисовки. Код после этой строки выполнится только после закрытия окна.
Если забыть mainloop() и запустить файл двойным щелчком, окно мелькнет и сразу исчезнет. В интерактивной оболочке IDLE окно может появиться и без этого вызова, что сбивает с толку.
Надпись и кнопка с обработчиком
Элементы интерфейса в Tkinter называются виджетами. Каждый виджет создается с указанием родителя, то есть окна или контейнера, в котором он будет жить, а потом размещается одним из менеджеров геометрии.
import tkinter as tk
clicks = 0
def on_click():
global clicks
clicks += 1
label.config(text=f"Нажатий: {clicks}")
root = tk.Tk()
root.title("Счетчик")
root.geometry("300x150")
label = tk.Label(root, text="Нажмите кнопку", font=("Arial", 14))
label.pack(pady=20)
button = tk.Button(root, text="Нажать", command=on_click)
button.pack()
root.mainloop()Label выводит текст, Button рисует кнопку, а метод config() меняет свойства виджета на лету. Параметр pady добавляет отступ сверху и снизу. Функции, которые реагируют на действия пользователя, называют обработчиками; о том, как их объявлять, рассказано в статье про функции Python.
Почему command пишется без скобок
В command передается сама функция, а не результат ее вызова. Запись command=on_click() выполнит функцию один раз при создании кнопки, а нажатия потом ничего делать не будут. Если обработчику нужны аргументы, оберните вызов в lambda: command=lambda: greet("Анна").
Поле ввода и проверка данных
Для ввода текста служит виджет Entry. Его содержимое читается методом get() и всегда приходит строкой, поэтому числа нужно преобразовать самостоятельно. Ниже небольшой конвертер температуры с обработкой неверного ввода.
import tkinter as tk
from tkinter import messagebox
def convert():
try:
celsius = float(entry.get().replace(",", "."))
except ValueError:
messagebox.showerror("Ошибка", "Введите число")
return
fahrenheit = celsius * 9 / 5 + 32
result.config(text=f"{fahrenheit:.1f} °F")
root = tk.Tk()
root.title("Конвертер")
tk.Label(root, text="Градусы Цельсия:").grid(row=0, column=0, padx=10, pady=10)
entry = tk.Entry(root, width=10)
entry.grid(row=0, column=1, padx=10)
tk.Button(root, text="Перевести", command=convert).grid(row=1, column=0, columnspan=2)
result = tk.Label(root, text="")
result.grid(row=2, column=0, columnspan=2, pady=10)
root.mainloop()Модуль messagebox показывает стандартные диалоги: showinfo, showwarning, showerror, askyesno. Обратите внимание, что надпись слева создана и размещена в одну строку: ссылка на нее дальше не нужна. С полем ввода так делать нельзя: метод grid() возвращает None, и переменная потеряла бы виджет.
Размещение виджетов: pack, grid и place
Виджет не появится в окне, пока не вызван один из трех менеджеров геометрии. Они по-разному решают, где окажется элемент.
| Менеджер | Принцип | Когда подходит |
|---|---|---|
pack() | Складывает виджеты друг за другом сверху вниз или по сторонам (side="left") | Простые окна, панели кнопок |
grid() | Таблица из строк и столбцов, row и column | Формы с подписями и полями |
place() | Точные координаты x, y или доли размера окна | Редкие случаи с ручной разметкой |
Главное правило: внутри одного контейнера нельзя смешивать pack() и grid(). Tkinter выбросит TclError. Если нужны разные схемы, разбейте окно на несколько tk.Frame и в каждом используйте свой менеджер.
Современный вид через ttk
Классические виджеты выглядят старомодно, особенно на Windows. Подмодуль tkinter.ttk содержит тематические версии тех же элементов, которые рисуются в стиле операционной системы.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("ttk")
ttk.Label(root, text="Имя:").pack(padx=20, pady=(20, 5))
ttk.Entry(root).pack(padx=20)
ttk.Button(root, text="OK", command=root.destroy).pack(pady=20)
root.mainloop()У виджетов ttk часть параметров отличается: например, цвет фона и шрифт задаются через стили ttk.Style(), а не аргументами bg и font. Справку по всем виджетам и их опциям удобно держать под рукой; ссылки собраны на странице документации Tkinter, а исходное описание модуля есть на docs.python.org.
Частые вопросы
Ответы на вопросы, которые возникают после запуска первого окна.
Как убрать черное окно консоли при запуске?
На Windows сохраните файл с расширением .pyw или запускайте его через pythonw.exe. При сборке в исполняемый файл добавьте флаг --noconsole; как это сделать, описано в статье про PyInstaller.
Как запретить изменение размера окна?
Вызовите root.resizable(False, False). Первый аргумент отвечает за ширину, второй за высоту. Минимальный размер задается методом minsize().
Почему интерфейс зависает во время долгой операции?
Обработчик выполняется в том же потоке, что и mainloop(), и пока он работает, окно не перерисовывается. Долгие задачи выносят в отдельный поток или разбивают на части через root.after().
Как закрыть окно из кода?
Метод root.destroy() закрывает окно и завершает mainloop(). Его можно передать в command кнопки без скобок, как в примере с ttk.