Окно на Tkinter: Tk, Label, Entry, Button, command, grid/pack, messagebox

Вспомните: в уроке 2.1 программа спрашивала сумму через input() и в цикле с try/except переспрашивала, пока человек не введёт число. Работает, но коллеге, который не открывает терминал, такую программу не отдашь. В этом уроке у итогов расходов появится окно: поле для суммы, кнопка «Добавить» и надпись «Итого», а ошибка ввода будет всплывать отдельным окошком.

🎯 После урока сможете: создать окно через tk.Tk(), разместить в нём надпись, поле ввода и кнопку, прочитать и очистить поле, поменять текст надписи, привязать к кнопке свою функцию через command, разложить виджеты по сетке grid, показать ошибку через messagebox и проверить обработчик кнопки без окна — вызвав его прямо из кода.

Первое окно: Tk, title, geometry, mainloop

Tkinter входит в поставку Python с сайта python.org для Windows и macOS: устанавливать ничего не нужно (если Python на Mac поставлен через Homebrew, Tkinter добавляют отдельно: brew install python-tk). Модуль принято импортировать под коротким именем tk. Окно программы — это объект tk.Tk(), у него есть заголовок и размер.

import tkinter as tk

root = tk.Tk()
root.title("Калькулятор расходов")
root.geometry("320x160")
root.mainloop()
  • root = tk.Tk() — создаёт главное окно; имя root (корень) — общепринятое;
  • root.title("…") — текст в заголовке окна;
  • root.geometry("320x160") — размер в пикселях: ширина, латинская буква x, высота;
  • root.mainloop() — запускает цикл ожидания: окно висит на экране и реагирует на мышь и клавиатуру, пока его не закроют. Строки после mainloop() выполнятся только после закрытия окна.
Пустое окно Windows шириной 320 и высотой 160 пикселей. В заголовке слева значок пера Tk и текст «Калькулятор расходов», справа три кнопки: свернуть, развернуть, закрыть. Внутренняя область пустая, светло-серая. Снаружи размерные линии: по верхнему краю «320 px», по правому — «160 px».

Сохраните код в файл okno.py и запустите его как обычно: python okno.py. Появится пустое окно. Закройте его крестиком — программа завершится. На Linux, если Tkinter не найден, поставьте пакет python3-tk менеджером пакетов.

Проверьте себя

Контрольный вопрос. Какая строка держит окно на экране и заставляет его отвечать на нажатия, пока человек его не закроет?

Аroot = tk.Tk()
Бroot.title(«Расходы»)
Вroot.geometry(«320×160»)
Гroot.mainloop()

Подсказка: Вспомните, что происходит со строками кода, которые стоят после этой: когда они выполнятся?

Онлайн-проверка ответа появится позже

Задание. Какой высоты будет окно в пикселях? Введите число.

Исходный код для этого задания:

import tkinter as tk

root = tk.Tk()
root.title("Поиск в журнале")
root.geometry("480x220")
root.mainloop()

Подсказка: В строке размера два числа через букву x. Какое из них идёт первым — ширина или высота?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Надпись, поле и кнопка: Label, Entry, Button

Всё, что лежит в окне, называется виджетами. Для калькулятора нужны три:

  • tk.Label — надпись: текст, который человек читает, но не редактирует;
  • tk.Entry — поле ввода в одну строку;
  • tk.Button — кнопка.

Первым аргументом виджету передают окно, в котором он живёт (root), дальше — параметры: text — текст, width — ширина (у поля — в символах). Создать виджет мало — его нужно ещё разместить в окне. Самый простой способ — pack(): виджеты встают друг под другом в порядке вызова. Параметр pady добавляет отступ сверху и снизу в пикселях.

import tkinter as tk

root = tk.Tk()
root.title("Калькулятор расходов")

label = tk.Label(root, text="Сумма покупки:")
label.pack(pady=5)
entry = tk.Entry(root, width=15)
entry.pack()
button = tk.Button(root, text="Добавить")
button.pack(pady=5)

root.mainloop()

Кнопка пока ничего не делает — это следующий раздел. Сначала научимся работать с полем и надписью из кода. У поля три метода:

  • entry.get() — вернуть текст из поля. Всегда строку, даже если там цифры;
  • entry.insert(0, "450") — вставить текст; 0 — позиция, с которой вставлять (начало поля);
  • entry.delete(0, tk.END) — удалить текст с позиции 0 до конца поля, то есть очистить его.

У надписи текст меняют методом config, а читают методом cget (от «configuration get»):

  • label.config(text="Итого: 450") — поставить новый текст;
  • label.cget("text") — прочитать текущий текст.

Эти методы работают и без показа окна: mainloop() не вызываем, окно так и не появится, а значения можно напечатать. В конце вызываем root.destroy() — он уничтожает окно и все виджеты в нём. Так удобно проверять код без мыши:

import tkinter as tk

root = tk.Tk()
entry = tk.Entry(root)
label = tk.Label(root, text="Итого: 0")

entry.insert(0, "450")
print(entry.get(), type(entry.get()))
entry.delete(0, tk.END)
print("После delete:", repr(entry.get()))
label.config(text="Итого: 450")
print(label.cget("text"))
root.destroy()

Вывод:

450 <class 'str'>
После delete: ''
Итого: 450

repr() печатает строку в кавычках — так видно, что поле стало пустым, а не пропало из вывода.

Проверьте себя

Контрольный вопрос. Нужен виджет, в который человек впечатает сумму покупки. Какой выбрать?

Аtk.Label
Бtk.Entry
Вtk.Button
Гtk.Tk

Подсказка: Какой из перечисленных виджетов позволяет человеку печатать текст, а не только читать его?

Онлайн-проверка ответа появится позже

Задание. Что напечатает программа? Введите строку вывода целиком.

Исходный код для этого задания:

import tkinter as tk

root = tk.Tk()
entry = tk.Entry(root)
label = tk.Label(root, text="Сумма: ?")

entry.insert(0, "450")
entry.delete(0, tk.END)
entry.insert(0, "1200")
label.config(text="Сумма: " + entry.get())
print(label.cget("text"))
root.destroy()

Подсказка: Проследите содержимое поля после каждой строки: что в нём остаётся после delete(0, tk.END) и что вставляется потом?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Задание. Человек ввёл в поле 25. Что напечатает программа? Введите вывод.

Исходный код для этого задания:

import tkinter as tk

root = tk.Tk()
entry = tk.Entry(root)
entry.insert(0, "25")

print(entry.get() * 2)
root.destroy()

Подсказка: Какого типа значение возвращает entry.get()? Что делает умножение на 2 со значением такого типа?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

command: что делать по нажатию кнопки

Чтобы кнопка работала, пишут обычную функцию без параметров и передают её имя в параметр command. Tkinter сам вызовет функцию при каждом нажатии. Такую функцию называют обработчиком.

Итог должен жить между нажатиями, поэтому храним его в переменной вне функции. Чтобы функция могла её изменить, внутри пишут global total — «это переменная из программы, а не новая местная». Без этой строки total = total + … внутри функции даст ошибку UnboundLocalError. Если функция меняет несколько таких переменных, их перечисляют в одной строке через запятую: global total, errors.

import tkinter as tk

total = 0


def add():
    global total
    total = total + int(entry.get())
    label.config(text=f"Итого: {total}")
    entry.delete(0, tk.END)


root = tk.Tk()
root.title("Калькулятор расходов")
entry = tk.Entry(root, width=15)
entry.pack(pady=5)
button = tk.Button(root, text="Добавить", command=add)
button.pack()
label = tk.Label(root, text="Итого: 0")
label.pack(pady=5)

root.mainloop()

Функция add объявлена выше, чем создаются entry и label, но это не мешает: к моменту нажатия кнопки вся программа уже выполнена до mainloop(), и виджеты существуют.

Пишите command=add — без скобок. Со скобками command=add() функция выполнится сразу, в момент создания кнопки, а не по нажатию. В калькуляторе поле в этот момент уже есть, но оно пустое: int("") даст ValueError, и программа остановится, окно так и не появится. А если функция и не упадёт, в command попадёт то, что она вернула, — None, и нажатия потом ничего делать не будут.

Проверить обработчик можно без мыши: вставить текст в поле и вызвать add() прямо из кода — ровно то же, что делает кнопка. Этот приём понадобится в заданиях и миссиях:

import tkinter as tk

total = 0


def add():
    global total
    total = total + int(entry.get())
    label.config(text=f"Итого: {total}")
    entry.delete(0, tk.END)


root = tk.Tk()
entry = tk.Entry(root)
label = tk.Label(root, text="Итого: 0")

for s in ["450", "380", "620"]:
    entry.insert(0, s)
    add()
print(label.cget("text"))
root.destroy()

Вывод:

Итого: 1450

Проверьте себя

Контрольный вопрос. Сразу после запуска надпись показывает «Итого: 0», хотя кнопку «Сброс» никто не нажимал, а нажатия потом ничего не меняют. В чём ошибка?

Исходный код для этого задания:

import tkinter as tk

total = 900


def reset():
    global total
    total = 0
    label.config(text="Итого: 0")


root = tk.Tk()
label = tk.Label(root, text="Итого: 900")
label.pack()
button = tk.Button(root, text="Сброс", command=reset())
button.pack()
root.mainloop()
Ав command передан результат вызова reset(), а нужно имя reset
Бне хватает return в функции reset
Вglobal total нужно убрать
Гкнопку нужно создавать до надписи

Подсказка: Сравните строку создания кнопки с правилом из материала: что должно стоять после command= — имя функции или её вызов?

Онлайн-проверка ответа появится позже

Задание. Человек нажал кнопку 4 раза. Что будет написано на надписи? Введите текст надписи целиком.

Исходный код для этого задания:

import tkinter as tk

cups = 0


def click():
    global cups
    cups = cups + 2
    label.config(text=f"Чашек: {cups}")


root = tk.Tk()
label = tk.Label(root, text="Чашек: 0")
label.pack()
tk.Button(root, text="Выпил", command=click).pack()
root.mainloop()

Подсказка: Каждое нажатие — один вызов click(). На сколько меняется cups за один вызов?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Раскладка по сетке: grid

pack() ставит виджеты столбиком. Для формы «подпись слева — поле справа» удобнее сетка grid: окно делится на строки и столбцы, у каждого виджета указывают row (номер строки) и column (номер столбца). Нумерация с нуля, как в списках.

import tkinter as tk

root = tk.Tk()
root.title("Калькулятор расходов")

tk.Label(root, text="Сумма:").grid(row=0, column=0, padx=5, pady=5)
entry = tk.Entry(root, width=12)
entry.grid(row=0, column=1, padx=5)
tk.Button(root, text="Добавить").grid(row=0, column=2, padx=5)
label = tk.Label(root, text="Итого: 0")
label.grid(row=1, column=0, columnspan=3, pady=5)

root.mainloop()
  • padx, pady — отступы слева-справа и сверху-снизу;
  • columnspan=3 — виджет занимает три столбца подряд: надпись «Итого» растягивается под всей первой строкой;
  • sticky="w" — прижать виджет к стороне ячейки: "w" — влево (запад), "e" — вправо (восток).

Если виджет создан сразу в одной строке с .grid(...), как tk.Label(...).grid(...), в переменную его не сохраняют: grid() возвращает None. Для надписей, которые не меняются, так и делают. А поле и надпись «Итого» мы будем читать и менять — их сначала кладём в переменную, потом размещаем.

В одном окне выберите что-то одно: pack или grid. Если часть виджетов окна разместить через pack, а часть — через grid, Tkinter остановит программу с ошибкой TclError.

Окно «Калькулятор расходов» с наложенной пунктирной сеткой из двух строк и трёх столбцов. Над столбцами подписи column 0, column 1, column 2, слева от строк — row 0 и row 1. В строке 0: надпись «Сумма:», пустое поле ввода и кнопка «Добавить». В строке 1 надпись «Итого: 0» растянута на все три столбца, рядом пометка columnspan=3.

Проверьте себя

Контрольный вопрос. Где окажется кнопка «Найти»?

Исходный код для этого задания:

import tkinter as tk

root = tk.Tk()
tk.Label(root, text="Слово:").grid(row=0, column=0)
entry = tk.Entry(root)
entry.grid(row=0, column=1)
tk.Button(root, text="Найти").grid(row=1, column=1)
root.mainloop()
Асправа от поля, в той же строке
Бпод полем ввода
Впод надписью «Слово:»
Гнад полем ввода

Подсказка: Сравните row и column кнопки с row и column поля: что совпадает, а что нет? Строки идут сверху вниз.

Онлайн-проверка ответа появится позже

Контрольный вопрос. Программа при запуске остановилась с ошибкой TclError. Почему?

Исходный код для этого задания:

import tkinter as tk

root = tk.Tk()
tk.Label(root, text="Сумма:").grid(row=0, column=0)
entry = tk.Entry(root)
entry.grid(row=0, column=1)
tk.Button(root, text="Добавить").pack()
root.mainloop()
Ав одном окне смешаны grid и pack
Бу кнопки нет command
Вполе не сохранено в переменную
Гне указан размер окна через geometry

Подсказка: Посмотрите, каким способом размещён каждый виджет этого окна, и сверьтесь с предупреждением в материале.

Онлайн-проверка ответа появится позже

messagebox: сообщить об ошибке отдельным окошком

Ввод в окне ничем не лучше ввода в терминале: человек напишет «сто» или «12,5». Ловим это тем же try/except, что в уроке 2.1, но сообщение показываем не print, а всплывающим окном. Модуль messagebox нужно импортировать отдельно: from tkinter import messagebox.

  • messagebox.showinfo("Заголовок", "Текст") — сообщение со значком «i»;
  • messagebox.showwarning(…) — предупреждение, жёлтый значок;
  • messagebox.showerror(…) — ошибка, красный значок;
  • messagebox.askyesno("Заголовок", "Вопрос?") — вопрос с кнопками «Да» и «Нет»; возвращает True, если нажали «Да», и False, если «Нет».

Первый аргумент — заголовок окошка, второй — текст. Пока окошко открыто, программа ждёт: следующая строка обработчика выполнится только после нажатия OK.

from tkinter import messagebox


def add():
    global total
    try:
        amount = float(entry.get().replace(",", "."))
        if amount <= 0:
            raise ValueError("сумма должна быть больше нуля")
    except ValueError:
        messagebox.showerror("Ошибка ввода", "Введите сумму числом больше нуля, например 450 или 99,90")
    else:
        total = total + amount
        label.config(text=f"Итого: {total:.2f}")
    entry.delete(0, tk.END)

Здесь работают приёмы урока 2.1: запятая меняется на точку, float даёт ValueError на «сто», а свой raise отбраковывает ноль и минус. Итог обновляется только в else — при удачном разборе. Запись {total:.2f} в f-строке печатает число с двумя знаками после точки: 450.0 превратится в 450.00. Поле очищается в любом случае, чтобы человек ввёл заново.

Поверх окна «Калькулятор расходов» открыто маленькое окно-сообщение с заголовком «Ошибка ввода». Слева в нём красный круг с белым крестом, справа текст «Введите сумму числом больше нуля, например 450 или 99,90», ниже кнопка OK. В основном окне под ним видно поле с текстом «сто» и надпись «Итого: 450.00» — до этого ввели 450.

Проверьте себя

Контрольный вопрос. Человек ввёл в поле даты «31.02.2026». Какой вызов покажет окно ошибки с красным значком?

Аmessagebox.showinfo(«Дата», «Такой даты нет»)
Бmessagebox.showerror(«Дата», «Такой даты нет»)
Вmessagebox.askyesno(«Дата», «Такой даты нет»)
Гprint(«Такой даты нет»)

Подсказка: Вспомните список функций messagebox: у какой из них значок ошибки?

Онлайн-проверка ответа появится позже

Задание. При вызове clear() откроется вопрос, и человек нажмёт «Нет». Что напечатает программа? Введите строку вывода целиком.

Исходный код для этого задания:

import tkinter as tk
from tkinter import messagebox

total = 3700


def clear():
    global total
    if messagebox.askyesno("Сброс", "Обнулить итог?"):
        total = 0
    label.config(text=f"Итого: {total}")


root = tk.Tk()
label = tk.Label(root, text="Итого: 3700")
clear()
print(label.cget("text"))
root.destroy()

Подсказка: Что возвращает askyesno при нажатии «Нет»? Выполнится ли тогда строка внутри if?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Собираем калькулятор расходов

Соберём всё вместе: сетка из урока, обработчик с проверкой ввода и кнопка «Сбросить» с вопросом. Это полная программа — её можно запускать.

import tkinter as tk
from tkinter import messagebox

total = 0


def add():
    global total
    try:
        amount = float(entry.get().replace(",", "."))
        if amount <= 0:
            raise ValueError("сумма должна быть больше нуля")
    except ValueError:
        messagebox.showerror("Ошибка ввода", "Введите сумму числом больше нуля, например 450 или 99,90")
    else:
        total = total + amount
        label.config(text=f"Итого: {total:.2f}")
    entry.delete(0, tk.END)


def reset():
    global total
    if messagebox.askyesno("Сброс", "Обнулить итог?"):
        total = 0
        label.config(text="Итого: 0.00")


root = tk.Tk()
root.title("Калькулятор расходов")

tk.Label(root, text="Сумма:").grid(row=0, column=0, padx=5, pady=5)
entry = tk.Entry(root, width=12)
entry.grid(row=0, column=1, padx=5)
tk.Button(root, text="Добавить", command=add).grid(row=0, column=2, padx=5)
label = tk.Label(root, text="Итого: 0.00")
label.grid(row=1, column=0, columnspan=2, pady=5)
tk.Button(root, text="Сбросить", command=reset).grid(row=1, column=2, padx=5)

root.mainloop()
Готовое окно «Калькулятор расходов». Верхняя строка: надпись «Сумма:», пустое белое поле ввода и кнопка «Добавить». Нижняя строка: надпись «Итого: 1250.00» слева и кнопка «Сбросить» справа.

Запустите программу у себя, введите несколько сумм, потом «сто», «-20» и «12,5». Посмотрите, какие попали в итог, а какие вызвали окно ошибки. Нажмите «Сбросить» и ответьте «Нет», затем «Да».

Проверьте себя

Задание. Окна ошибок в этой программе при проверке просто закрываются кнопкой OK. Что она напечатает? Введите два числа через пробел, как в выводе.

Исходный код для этого задания:

import tkinter as tk
from tkinter import messagebox

total = 0
errors = 0


def add():
    global total, errors
    try:
        amount = float(entry.get().replace(",", "."))
        if amount <= 0:
            raise ValueError("сумма должна быть больше нуля")
    except ValueError:
        errors = errors + 1
        messagebox.showerror("Ошибка", "Нужна сумма больше нуля")
    else:
        total = total + amount
    entry.delete(0, tk.END)


root = tk.Tk()
entry = tk.Entry(root)

for s in ["250", "двести", "99,5", "0", "", "150,5"]:
    entry.insert(0, s)
    add()
print(total, errors)
root.destroy()

Подсказка: Для каждой строки списка решите: превращается ли она в число после замены запятой, проходит ли проверку amount <= 0, в какую ветку уходит — else или except.

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Задание. В этом обработчике после ошибки стоит return, поэтому поле при ошибке не очищается, а insert(0, …) дописывает новый текст в начало того, что там осталось. Что напечатает программа первой строкой? Введите строку целиком.

Исходный код для этого задания:

import tkinter as tk
from tkinter import messagebox

total = 0


def add():
    global total
    try:
        amount = int(entry.get())
    except ValueError:
        messagebox.showerror("Ошибка", "Введите целое число")
        return
    total = total + amount
    label.config(text=f"Итого: {total}")
    entry.delete(0, tk.END)


root = tk.Tk()
entry = tk.Entry(root)
label = tk.Label(root, text="Итого: 0")

for s in ["300", "12,5", "200"]:
    entry.insert(0, s)
    add()
print(label.cget("text"))
print(repr(entry.get()))
root.destroy()

Подсказка: Проследите содержимое поля после каждого вызова add(): что остаётся в нём после ошибки и что получится, когда в начало вставят следующую строку?

✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.

Онлайн-проверка ответа появится позже

Задание. Соберите сами окно «Учёт чтения»: поле для числа прочитанных минут, кнопка «Добавить» и надпись «Всего минут: …». Обработчик превращает текст поля в int, отбраковывает через raise ValueError число ≤ 0, при ошибке показывает messagebox.showwarning, при успехе прибавляет минуты к итогу и меняет надпись; поле очищается в любом случае. Проверьте обработчик без мыши: в конце программы вместо mainloop() по очереди вставляйте в поле строки из списка ниже и вызывайте обработчик. В поле ответа — число, которое окажется на надписи.

["5", "10", "", "пять", "15", "-5", "20", "0", "7", "десять", "13", "30"]

Подсказка: Возьмите за основу калькулятор расходов из урока: те же три виджета, global для итога, try/except/else. Проверка — цикл for со вставкой в поле и вызовом обработчика, как в разделе про command.

✅ Готово, если: ответ раскрывает то, что просит критерий приёмки в задании выше.

Онлайн-проверка ответа появится позже

Задание. Проектная миссия «Калькулятор расходов для коллеги». Сделайте окно: подпись «Сумма:», поле, кнопка «Добавить», надпись «Итого: …» с двумя знаками после точки и кнопка «Сбросить» с вопросом askyesno. Обработчик принимает дробную часть через запятую, отбраковывает через raise ValueError сумму ≤ 0, на плохом вводе показывает messagebox.showerror и считает ошибки. Ниже — 51 строка, которую коллега ввёл в поле по очереди за месяц (каждая строка — одно содержимое поля; пустая строка — нажал «Добавить» с пустым полем). Для проверки добавьте переменную SHOW_ERRORS: при False окно ошибки не показывается, только считается, — и прогоните строки через поле и обработчик циклом, как в уроке. В поле ответа — итог, округлённый round() до целого. Приложите файл программы .py; в поле ответа — число.

Принято, если:
1. введённое число совпадает с эталоном;
2. приложен файл .py, который это число выдаёт на данных из условия;

Самопроверка перед сдачей (преподаватель смотрит на занятии):
3. раскладка по grid, pack в том же окне не используется;
4. в command передано имя функции без скобок;
5. при SHOW_ERRORS = True на «сто» всплывает окно ошибки, итог не меняется.

357

632

1014

2990,51

2124

273

1960

43

сто

3241,11

2028

3492,46

866

1408,77

-150

498

1837,16

196

968,49

3023

0

726

3368

2368

377

2444,46

12р

1389,94

1681

1225

325

77

двести

1864,21

295,43

237

636

832

-5,5

2045,77

2860

1516

1062

2191

1 200

995,58

2418

839

2128,97

3406

Подсказка: Начните с калькулятора из урока и добавьте счётчик ошибок в ветку except. Строки данных удобно вставить в программу списком и пройти циклом for: insert в поле, вызов обработчика.

✅ Готово, если: ответ раскрывает то, что просит критерий приёмки в задании выше.

Онлайн-проверка ответа появится позже

Задание. Проектная миссия «Расходы по категориям». Сделайте окно на grid: в первой строке подпись «Категория:» и поле, во второй — «Сумма:» и поле, в третьей — кнопка «Добавить», в четвёртой — надпись с итогом той категории, в которую только что добавили (например «кафе: 1840»). Итоги храните в словаре «категория → сумма». Пустая категория, нечисловая сумма и сумма ≤ 0 — ValueError (свой raise для пустой категории и для ≤ 0), messagebox.showwarning, запись не учитывается. Оба поля очищаются после каждого нажатия. Ниже — 48 записей «категория;сумма», которые ввели в окно по очереди (слева от «;» — что было в поле категории, справа — в поле суммы). Прогоните их через поля и обработчик циклом, окна предупреждений для прогона отключите переменной, как в первой миссии. В поле ответа — итог категории «продукты». Приложите файл программы .py; в поле ответа — число.

Принято, если:
1. введённое число совпадает с эталоном;
2. приложен файл .py, который это число выдаёт на данных из условия;

Самопроверка перед сдачей (преподаватель смотрит на занятии):
3. итоги хранятся в словаре, а не в отдельной переменной на каждую категорию;
4. подписи и поля выровнены по сетке, надпись итога меняется через config.

кафе;624

транспорт;64

;172

продукты;64

транспорт;1353

связь;0

связь;401

кафе;1837

транспорт;1557

;398

транспорт;591

кафе;2036

кафе;1605

продукты;202

транспорт;сто

транспорт;2230

;1605

транспорт;528

связь;1363

транспорт;699

транспорт;1871

продукты;1905

продукты;82

;сто

продукты;588

кафе;404

продукты;2119

транспорт;1445

продукты;1309

транспорт;1010

;472

транспорт;139

продукты;-300

кафе;2139

кафе;819

продукты;1555

продукты;150

;788

продукты;417

транспорт;1603

связь;277

транспорт;-300

транспорт;867

кафе;421

;958

продукты;1378

связь;2327

кафе;691

Подсказка: Разбирайте запись через split(«;») уже в цикле проверки, а обработчик пусть читает только поля — как кнопка в настоящем окне. Для словаря пригодится get(категория, 0).

✅ Готово, если: ответ раскрывает то, что просит критерий приёмки в задании выше.

Онлайн-проверка ответа появится позже

Что дальше

Теперь вы умеете создавать окно через tk.Tk(), класть в него надписи, поля и кнопки, раскладывать их по сетке grid, читать и очищать поле, менять текст надписи, привязывать к кнопке функцию через command, сообщать об ошибке ввода через messagebox и проверять обработчик без мыши. В следующем уроке окно станет настоящей утилитой: научим его выбирать файл через диалог, показывать список, ставить галочки и запоминать настройки в JSON между запусками.

← Назад · ↑ В начало урока · ⌂ К навигатору курса · Вперёд →

Школа Виктора Комлева