Разработка GUI приложений на Python: библиотека Tkinter

Раздел: Разработка на Python -> Графический интерфейс

Основы Tkinter: построение оконного интерфейса

Как создать окно с кнопкой и реакцией на нажатие?

Наиболее простой и эффективный способ - создать класс, наследующий от tk.Tk, и разместить в нём виджеты. Такой подход позволяет легко управлять состоянием приложения и избегать глобальных переменных.


import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Пример приложения")
        self.geometry("300x200")

        self.label = tk.Label(self, text="Привет, мир!")
        self.label.pack(pady=20)

        self.button = tk.Button(self, text="Нажми меня", command=self.change_label)
        self.button.pack()

    def change_label(self):
        self.label.config(text="Кнопка нажата!")

if __name__ == "__main__":
    app = App()
    app.mainloop()
    

вывод окна python (создание окна с выводом в python)

Пояснение: конструктор класса вызывает super().__init__() для создания главного окна. Виджеты Label и Button упаковываются менеджером pack(). Команда кнопки привязана к методу change_label, который изменяет текст метки. Запуск цикла обработки событий mainloop() обязателен.

Типичная ошибка: забытый вызов mainloop() - окно не появится. Также часто путают command: передают результат функции (с круглыми скобками), а не ссылку. Исправляется передачей имени функции без скобок.

Если окно зависает при нажатии, проверьте, не блокирует ли выполнение длительная операция. Для фоновых задач используйте after() или потоки.

Как размещать виджеты с помощью сетки (grid)?

Менеджер grid позволяет размещать элементы в табличной структуре. Он удобен для форм ввода данных.


from tkinter import *

root = Tk()
root.title("Сетка")

Label(root, text="Имя:").grid(row=0, column=0, sticky="e", padx=5, pady=5)
entry_name = Entry(root)
entry_name.grid(row=0, column=1, padx=5, pady=5)

Label(root, text="Пароль:").grid(row=1, column=0, sticky="e", padx=5, pady=5)
entry_pass = Entry(root, show="*")
entry_pass.grid(row=1, column=1, padx=5, pady=5)

Button(root, text="Войти", command=lambda: print(f"Вход: {entry_name.get()}")).grid(row=2, column=1, pady=10)

root.mainloop()
    

открыть окно python (открыть окно на python)

sticky=\"e\" выравнивает метку вправо. padx/pady добавляют отступы.

Ошибка: смешение pack и grid в одном контейнере приводит к ошибке выполнения. Используйте только один менеджер для одного родительского виджета.

Как обрабатывать ввод текста и выводить результат?

Соединим Entry, Button и Label для простого конвертера.


from tkinter import *

def convert():
    try:
        celsius = float(entry.get())
        fahr = celsius * 9/5 + 32
        result_label.config(text=f"{fahr:.1f} °F")
    except ValueError:
        result_label.config(text="Ошибка ввода")

root = Tk()
root.title("Конвертер")

Label(root, text="Градусы Цельсия:").pack()
entry = Entry(root)
entry.pack()

Button(root, text="Перевести", command=convert).pack(pady=5)
result_label = Label(root, text="")
result_label.pack()

root.mainloop()
    

Python окно (создание окон в python tkinter)

В функции convert получаем текст из поля, преобразуем в число, вычисляем и обновляем метку. Обработка исключений предотвращает падение при нечисловом вводе.

Проблема: при каждом вызове pack() для результата не нужно создавать новый виджет - обновляйте существующий через config().

Как создать диалоговое окно (например, сообщение)?

Библиотека messagebox предоставляет стандартные диалоги.


from tkinter import *
from tkinter import messagebox

def show_info():
    messagebox.showinfo("Информация", "Это окно с информацией")

def ask_question():
    result = messagebox.askyesno("Вопрос", "Вы уверены?")
    if result:
        alert_label.config(text="Да")
    else:
        alert_label.config(text="Нет")

root = Tk()
Button(root, text="Инфо", command=show_info).pack()
Button(root, text="Вопрос", command=ask_question).pack()
alert_label = Label(root, text="")
alert_label.pack()
root.mainloop()
    

Методы showinfo, askyesno возвращают результат (True/False), который можно использовать в логике.

Ошибка: забытый импорт from tkinter import messagebox. Если используется import tkinter as tk, то обращаться как tk.messagebox.showinfo(...).

- Python tkinter messagebox (messagebox в tkinter)
- Tkinter python ввод (ввод данных в tkinter)
- Python tkinter виджет (виджеты tkinter)

Расширенные примеры демонстрируют более сложные сценарии использования Tkinter.

Пример многооконного приложения

Пример

import tkinter as tk

def open_new_window():
    new = tk.Toplevel(root)
    new.title("Дочернее окно")
    new.geometry("200x100")
    tk.Label(new, text="Новое окно").pack()

root = tk.Tk()
root.title("Главное окно")
btn = tk.Button(root, text="Открыть новое окно", command=open_new_window)
btn.pack(pady=20)
root.mainloop()
Результат: при нажатии появляется второе окно, которое можно закрыть независимо.

Рисование на холсте Canvas

Пример

from tkinter import *

root = Tk()
root.title("Холст")

c = Canvas(root, width=300, height=200, bg="white")
c.pack()

# Рисуем овал
c.create_oval(50, 50, 150, 100, fill="blue")
# Прямоугольник
c.create_rectangle(180, 30, 280, 130, fill="red", outline="black")
# Линия
c.create_line(0, 200, 150, 0, width=3, fill="green")
# Текст
c.create_text(150, 180, text="Привет, Canvas", font=("Arial", 12))

root.mainloop()
На холсте появятся геометрические фигуры и текст.

Использование привязки клавиш (bind)

Пример

from tkinter import *

def key_pressed(event):
    print(f"Нажата клавиша: {event.keysym} (код: {event.keycode})")

def mouse_click(event):
    print(f"Клик мыши в координатах ({event.x}, {event.y})")

root = Tk()
root.title("События")
root.geometry("300x200")

root.bind("<Key>", key_pressed)
root.bind("<Button-1>", mouse_click)

Label(root, text="Нажмите любую клавишу или кликните мышью").pack()

root.mainloop()
В консоль выводятся данные о нажатых клавишах и координатах клика.

Таймер с отсчётом (after)

Пример

from tkinter import *

count = 10

def update_timer():
    global count
    if count > 0:
        timer_label.config(text=f"Осталось: {count} сек")
        count -= 1
        root.after(1000, update_timer)  # рекурсивный вызов через 1 секунду
    else:
        timer_label.config(text="Время вышло!")

root = Tk()
timer_label = Label(root, font=("Arial", 20))
timer_label.pack(pady=50)
update_timer()
root.mainloop()
Каждую секунду обновляется текст с уменьшающимся числом.

Диалог выбора файла и сохранения

Пример

from tkinter import *
from tkinter import filedialog

def open_file():
    filepath = filedialog.askopenfilename(
        title="Выберите файл",
        filetypes=(("Текстовые файлы", "*.txt"), ("Все файлы", "*.*"))
    )
    if filepath:
        with open(filepath, "r", encoding="utf-8") as f:
            text.delete("1.0", END)
            text.insert(END, f.read())

def save_file():
    filepath = filedialog.asksaveasfilename(
        title="Сохранить как",
        defaultextension=".txt",
        filetypes=(("Текстовые файлы", "*.txt"), ("Все файлы", "*.*"))
    )
    if filepath:
        with open(filepath, "w", encoding="utf-8") as f:
            f.write(text.get("1.0", END))

root = Tk()
root.title("Текстовый редактор")

frame = Frame(root)
frame.pack()

Button(frame, text="Открыть", command=open_file).pack(side=LEFT)
Button(frame, text="Сохранить", command=save_file).pack(side=LEFT)

text = Text(root, wrap=WORD)
text.pack(fill=BOTH, expand=True)

root.mainloop()
Приложение позволяет открыть текстовый файл, отредактировать и сохранить.

Программа на Python с графическим интерфейсом (tkinter) - comments

En
Tkinter python программы (python)