GUI на Python: графический интерфейс на tkinter и других библиотеках

GUI на Python: графический интерфейс на tkinter и других библиотеках Полезное

GUI (Graphical User Interface, графический интерфейс) — это оболочка программы, через которую пользователь работает мышью и клавиатурой с окнами, кнопками, полями ввода и меню, а не набирает текстовые команды. На Python такой интерфейс не пишут с нуля: берут готовую библиотеку виджетов, самая доступная из которых — встроенная tkinter.

Ниже разберу, чем GUI отличается от командной строки, какую библиотеку выбрать под задачу в 2026 году, и по шагам соберу первое оконное приложение на tkinter — калькулятор индекса массы тела. Весь код прогнан, консольный вывод в статье — реальный.

GUI и CLI: в чем разница

Эти два понятия удобно развести сразу, потому что библиотеки для них разные.

CLI (Command Line Interface) — текстовый интерфейс: программа читает команды из терминала и печатает ответ строками. Так работают git, pip, оболочка Linux и «Командная строка» Windows. В Python простой CLI пишется на голых input() и print() или на модуле argparse.

GUI — графический интерфейс: те же действия пользователь выполняет визуально, кликая по элементам окна. Для этого нужен набор виджетов (кнопка, поле, список) и цикл обработки событий, который реагирует на клики и ввод. Как раз это дают GUI-библиотеки.

Одно не «лучше» другого: CLI выигрывает в скриптах и автоматизации, GUI — там, где программой пользуется человек без привычки к терминалу.

Библиотеки для GUI на Python: что выбрать

У Python нет единственно правильной GUI-библиотеки — выбор зависит от задачи: учебный проект, десктопное приложение, мобильное или с web-версткой. Ниже — ориентир по задачам, а не полный каталог.

Библиотека На чем основана Когда брать
tkinter обертка над Tcl/Tk, входит в стандартную библиотеку учеба, утилиты, небольшие десктопные окна — ставить ничего не нужно
PyQt / PySide привязка к фреймворку Qt (C++) сложные десктопные приложения, богатый набор виджетов, редактор форм Qt Designer
wxPython обертка над нативным wxWidgets десктоп с «родным» видом окна под каждую ОС
Kivy собственный движок на OpenGL мультимедиа и мобильные приложения (Android, iOS), нестандартный интерфейс
Flet / Toga Flutter и нативные виджеты один код на десктоп, web и мобильные — более новый подход

Про пары PyQt и PySide стоит знать различие: обе привязывают Python к Qt и почти одинаковы по API, но у них разные лицензии. PyQt распространяется под GPL или платной коммерческой лицензией, а PySide (официальный проект Qt) — под более свободной LGPL, что удобнее для закрытых продуктов.

Отдельный класс — библиотеки, где интерфейс верстается на HTML и CSS, а Python работает бэкендом (например, Eel). Они удобны, если уже знаком с web-версткой, но тянут за собой браузерный движок, поэтому для простой утилиты избыточны. Начинать разбираться с GUI проще всего с tkinter: он уже установлен вместе с Python и не требует внешних зависимостей.

Первое приложение на tkinter: калькулятор ИМТ

Соберу маленькое, но законченное оконное приложение — калькулятор индекса массы тела (ИМТ). Пользователь вводит рост и вес, нажимает кнопку и получает во всплывающем окне значение и категорию. На этом примере видно все основные части GUI: окно, виджеты, обработчик события.

Шаг 1. Сначала логика, без интерфейса

Прежде чем рисовать окно, полезно отдельно написать и проверить расчет — тогда ошибка в формуле не спутается с ошибкой в интерфейсе. ИМТ считают по формуле ВОЗ: вес в килограммах делят на квадрат роста в метрах.

def bmi(weight_kg, height_cm):
    height_m = height_cm / 100          # переводим сантиметры в метры
    value = weight_kg / height_m ** 2   # формула ВОЗ: вес / рост в квадрате
    if value < 18.5:
        category = "недостаточный вес"
    elif value < 25:
        category = "норма"
    elif value < 30:
        category = "избыточный вес"
    else:
        category = "ожирение"
    return round(value, 1), category

for w, h in [(70, 180), (95, 175), (52, 165)]:
    value, category = bmi(w, h)
    print(f"{w} кг, {h} см -> ИМТ {value} ({category})")

Вывод программы:

70 кг, 180 см -> ИМТ 21.6 (норма)
95 кг, 175 см -> ИМТ 31.0 (ожирение)
52 кг, 165 см -> ИМТ 19.1 (норма)

Логика работает и не зависит от интерфейса. Теперь эту же классификацию можно подключить к окну.

Шаг 2. Окно, виджеты и обработчик

В tkinter приложение строится из трех вещей: главного окна (Tk), виджетов внутри него и функции-обработчика, которую вызывает кнопка. Виджеты в этом примере:

  • Label — текстовая надпись («Введите свой рост, см»).
  • Entry — однострочное поле ввода для роста и веса.
  • Button — кнопка «Рассчитать ИМТ», запускающая расчет.
  • messagebox — готовое всплывающее окно с ответом.

Расставлять виджеты по окну помогает менеджер геометрии. В tkinter их три: pack (складывает элементы блоками), place (по точным координатам) и grid (по ячейкам сетки). Для формы из подписей и полей удобнее всего grid — он выравнивает элементы по строкам и столбцам.

Вот полная программа целиком — ее можно скопировать в файл и запустить:

import tkinter as tk
from tkinter import messagebox

def calculate():
    try:
        height_cm = float(height_entry.get())   # читаем текст из полей
        weight_kg = float(weight_entry.get())
    except ValueError:
        messagebox.showerror("Ошибка", "Введите рост и вес числами")
        return
    value = weight_kg / (height_cm / 100) ** 2
    if value < 18.5:
        category = "недостаточный вес"
    elif value < 25:
        category = "норма"
    elif value < 30:
        category = "избыточный вес"
    else:
        category = "ожирение"
    messagebox.showinfo("Результат", f"ИМТ: {value:.1f}\nКатегория: {category}")

window = tk.Tk()
window.title("Калькулятор индекса массы тела (ИМТ)")
window.geometry("320x180")

frame = tk.Frame(window, padx=10, pady=10)
frame.pack()

tk.Label(frame, text="Введите свой рост, см").grid(row=0, column=0, sticky="w")
height_entry = tk.Entry(frame)
height_entry.grid(row=0, column=1)

tk.Label(frame, text="Введите свой вес, кг").grid(row=1, column=0, sticky="w")
weight_entry = tk.Entry(frame)
weight_entry.grid(row=1, column=1)

tk.Button(frame, text="Рассчитать ИМТ", command=calculate).grid(
    row=2, column=0, columnspan=2, pady=10)

window.mainloop()

Что произойдет при запуске: откроется окно размером 320×180 пикселей с заголовком «Калькулятор индекса массы тела (ИМТ)». В нем две подписи с полями ввода и кнопка. Если ввести рост 175 и вес 95 и нажать «Рассчитать ИМТ», поверх появится всплывающее окно с текстом «ИМТ: 31.0» и категорией «ожирение» — те же числа, что дала консольная проверка на шаге 1. Ввод не-числа (буквы, пустое поле) выведет окно с ошибкой, а не уронит программу.

Шаг 3. Разбор ключевых строк

Программа короткая, но в ней собраны все обязательные части GUI. Пройду по ним.

  • import tkinter as tk подключает библиотеку под коротким именем, а отдельный импорт messagebox нужен, потому что всплывающие окна лежат в подмодуле и через tk. не видны.
  • window = tk.Tk() создает главное окно; title задает заголовок, geometry("320x180") — стартовый размер.
  • Frame — контейнер с отступами padx/pady; виджеты кладут в него, а не прямо в окно, чтобы группировать элементы и управлять полями.
  • У каждого виджета вызывается grid(row=..., column=...) — это и есть размещение по сетке; columnspan=2 растягивает кнопку на два столбца, sticky="w" прижимает надпись влево.
  • command=calculate связывает кнопку с функцией: обработчик передается по имени, без скобок, иначе он выполнится сразу при создании кнопки, а не по клику.
  • window.mainloop() запускает цикл событий. Без этой строки программа завершится мгновенно, окно мелькнет и закроется — частая ошибка новичка.

Если окно не появляется

Типовые симптомы и что с ними делать:

  • Окно мелькнуло и сразу закрылось — забыли window.mainloop() в конце. Цикл событий не запущен, программа дошла до конца и вышла.
  • ModuleNotFoundError: No module named 'tkinter' — на Linux пакет Tk ставится отдельно (sudo apt install python3-tk); в стандартных сборках Python для Windows и macOS он уже есть.
  • Кнопка ничего не делает — в command передали calculate() со скобками. Тогда функция вызвалась один раз при старте, а кнопке досталось ее значение None. Правильно — имя без скобок: command=calculate.
  • ValueError в консоли при расчете — поле пустое или в него введен текст. В примере это перехвачено try/except и показано окном ошибки.

Выводы

  • GUI на Python — это графический интерфейс из окон и виджетов; в отличие от CLI, пользователь работает мышью, а не текстовыми командами.
  • Библиотеку выбирают под задачу: tkinter для учебы и утилит, PyQt/PySide для сложного десктопа, Kivy для мобильных и мультимедиа, wxPython для нативного вида; PyQt и PySide различаются лицензией.
  • Любое приложение на tkinter состоит из окна Tk, виджетов (Label, Entry, Button) и обработчика, привязанного к событию через command.
  • Виджеты размещают менеджером геометрии; для форм удобнее grid. Без mainloop() окно не остается на экране.

Где применяется и что учить дальше

Навык собирать простое окно пригодится для настольных утилит: калькуляторов, конвертеров, форм ввода, панелей запуска скриптов. Дальше обычно идут связка виджетов с данными, таблицы и графики, а для больших приложений — переход на Qt. Основа везде одна: разделить логику и интерфейс, как в примере выше.

Освойте тему на практике

Если хочется освоить Python системно — от синтаксиса и функций до работы с библиотеками и первых проектов — посмотрите курс Python Basic. Оценить формат и уровень до старта помогают бесплатные открытые уроки Otus — живые занятия с преподавателями.

Смежные темы: Python и его операторы.

FAQ

Нужно ли устанавливать tkinter отдельно? В стандартных сборках Python для Windows и macOS tkinter входит в комплект. На Linux модуль Tk иногда ставится отдельным пакетом (например, python3-tk в Debian и Ubuntu).

Чем grid отличается от pack и place? pack прижимает виджеты блоками к сторонам окна, place ставит их по точным координатам в пикселях, grid раскладывает по ячейкам таблицы (строка, столбец). Для форм с подписями и полями обычно берут grid. Смешивать pack и grid в одном контейнере нельзя.

Можно ли на tkinter сделать современный дизайн? Базовые виджеты выглядят старомодно, но подмодуль ttk дает темизированные элементы, а сторонние надстройки — более современный вид. Для сложного дизайна чаще берут Qt или web-подход.

OTUS Журнал