Работа с текстом в tkinter: от простого ввода до форматирования

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

Основные текстовые элементы в tkinter

Библиотека tkinter предоставляет несколько виджетов для работы с текстом: Label (метка), Entry (однострочное поле ввода), Text (многострочный редактор), Spinbox (поле ввода с выбором из списка) и ScrolledText (Text с автоматической прокруткой). Каждый из них используется в разных сценариях.

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

Наиболее универсальное решение для ввода и редактирования многострочного текста - виджет Text в сочетании с Scrollbar. Импортируйте tkinter и tkinter.scrolledtext для упрощения задачи.


import tkinter as tk
from tkinter import scrolledtext

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

# Создаем ScrolledText (уже содержит полосу прокрутки)
text_area = scrolledtext.ScrolledText(root, wrap=tk.WORD, width=40, height=10, font=("Arial", 12))
text_area.pack(padx=10, pady=10)

root.mainloop()
    

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

Пояснение:

  • wrap=tk.WORD - перенос по словам, предотвращает разрыв слов.
  • width и height задают размер виджета в символах.

Типичные ошибки:

  • Забывают импортировать scrolledtext - возникает ошибка NameError.
  • Указывают width в пикселях, а не символах - виджет становится слишком маленьким или большим.

Решение: всегда проверяйте импорты и используйте константы tk.CHAR (по умолчанию) для размеров.

Как отобразить статический текст?

Для вывода информации без возможности редактирования используйте виджет Label.


lbl = tk.Label(root, text="Привет, мир!", font=("Helvetica", 16))
lbl.pack()
    

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

Параметр font задает шрифт. Можно менять цвет текста через fg и фон через bg.

Проблема: текст не обновляется динамически. Решение - использовать метод config(text="новый текст").


lbl.config(text="Текст изменен")
        

Python tkinter canvas (холст canvas в tkinter)

Как получить введенный пользователем текст?

Виджет Entry предназначен для однострочного ввода. Для получения текста используется метод get().


entry = tk.Entry(root, width=30)
entry.pack()

def show_text():
    print(entry.get())

btn = tk.Button(root, text="Показать", command=show_text)
btn.pack()
    

Python tkinter frame (фрейм frame в tkinter)

Если поле пустое, get() вернет пустую строку. Добавьте проверку.

Ошибка: если пользователь ввел пробелы, они тоже считаются. Рекомендуется использовать .strip().

Как создать поле для выбора из заранее заданных значений?

Виджет Spinbox позволяет выбирать из списка строк или чисел. Параметр values принимает список.


spin = tk.Spinbox(root, values=("Яблоко", "Груша", "Вишня"), width=15)
spin.pack()
print(spin.get())  # выводит выбранное значение
    

Tkinter python ввод (ввод данных в tkinter)

Для чисел можно задать from_ и to.

Проблема: значения не обновляются при изменении списка. Решение: передавать новый список в config(values=...).

Как вставить форматированный текст или изображения в Text?

Виджет Text поддерживает теги и вставку виджетов (например, изображений) через window_create.


text = tk.Text(root, height=5)
text.pack()
text.insert(tk.END, "Жирный текст", "bold")
text.tag_config("bold", font=("Arial", 12, "bold"))

# Вставка изображения
from PIL import Image, ImageTk
img = Image.open("icon.png")
photo = ImageTk.PhotoImage(img)
text.image_create(tk.END, image=photo)
    

Изображение должно быть сохранено в переменной, иначе сборщик мусора удалит его.

Ошибка: изображение не отображается. Решение: хранить ссылку на photo как атрибут объекта (например, text.photo = photo).

- Python tkinter игра (игра на tkinter)
- Python tkinter root (главное окно tkinter (root))
- Python tkinter код (примеры кода tkinter)

Расширенные примеры работы с текстовыми элементами

Пример 1: Создание текстового редактора с подсветкой синтаксиса Python

Используем виджет Text и теги для выделения ключевых слов. Для демонстрации возьмем простой набор ключевых слов.

Пример

import tkinter as tk

root = tk.Tk()
root.title("Подсветка синтаксиса")

text = tk.Text(root, wrap=tk.WORD, bg="black", fg="white", insertbackground="white")
text.pack(fill=tk.BOTH, expand=True)

# Определяем теги
text.tag_config("keyword", foreground="cyan")
text.tag_config("string", foreground="yellow")
text.tag_config("comment", foreground="gray")

keywords = ["def", "class", "if", "else", "for", "while", "import", "return"]

def highlight(event=None):
    content = text.get("1.0", tk.END)
    text.mark_set("range_start", "1.0")
    text.mark_set("range_end", tk.END)
    text.tag_remove("keyword", "1.0", tk.END)
    text.tag_remove("string", "1.0", tk.END)
    text.tag_remove("comment", "1.0", tk.END)
    
    # Подсветка комментариев
    start_pos = "1.0"
    while True:
        pos = text.search("#", start_pos, tk.END)
        if not pos:
            break
        line_end = text.index(f"{pos} lineend")
        text.tag_add("comment", pos, line_end)
        start_pos = line_end
    
    # Подсветка ключевых слов
    for word in keywords:
        start_pos = "1.0"
        while True:
            pos = text.search(word, start_pos, tk.END, nocase=True)
            if not pos:
                break
            # Проверяем, что слово не часть другого слова
            prev_char = text.get(f"{pos} - 1 char")
            next_char = text.get(f"{pos} + {len(word)} chars")
            if not (prev_char.isalnum() or next_char.isalnum()):
                text.tag_add("keyword", pos, f"{pos} + {len(word)} chars")
            start_pos = f"{pos} + 1 char"
    
    # Подсветка строк (одинарные кавычки)
    start_pos = "1.0"
    while True:
        pos = text.search("'", start_pos, tk.END)
        if not pos:
            break
        end_pos = text.search("'", f"{pos} + 1 char", tk.END)
        if not end_pos:
            break
        text.tag_add("string", pos, f"{end_pos} + 1 char")
        start_pos = f"{end_pos} + 1 char"

text.bind("", highlight)
text.insert(tk.END, "# Это комментарий\ndef hello():\n    print('Hello')\n    return 42")
highlight()

root.mainloop()
Результат: окно с темным фоном, ключевые слова подсвечены голубым, строки желтым, комментарии серым.

Пример 2: Привязка горячих клавиш к текстовому полю

Добавим комбинации Ctrl+S (сохранить) и Ctrl+Z (отменить) для виджета Text.

Пример

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()
text = tk.Text(root)
text.pack(fill=tk.BOTH, expand=True)

undo_stack = []

def save():
    content = text.get("1.0", tk.END)
    with open("text.txt", "w", encoding="utf-8") as f:
        f.write(content)
    messagebox.showinfo("Сохранено", "Текст сохранен в text.txt")

def undo():
    if undo_stack:
        old = undo_stack.pop()
        text.delete("1.0", tk.END)
        text.insert("1.0", old)

def on_change(event=None):
    # Сохраняем текущее состояние
    undo_stack.append(text.get("1.0", tk.END))
    if len(undo_stack) > 20:
        undo_stack.pop(0)

text.bind("", lambda e: save())
text.bind("", lambda e: undo())
text.bind("", on_change)

root.mainloop()
Результат: при нажатии Ctrl+S вызывается функция save, при Ctrl+Z - отмена последнего изменения.

Пример 3: Использование Spinbox для выбора даты

Создадим три Spinbox для дня, месяца и года.

Пример

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title("Выбор даты")

day = tk.Spinbox(root, from_=1, to=31, width=5, justify=tk.CENTER)
month = tk.Spinbox(root, values=("Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"), width=5, justify=tk.CENTER)
year = tk.Spinbox(root, from_=1900, to=2100, width=5, justify=tk.CENTER)

def get_date():
    d = day.get()
    m = month.get()
    y = year.get()
    print(f"Выбрана дата: {d} {m} {y}")

btn = tk.Button(root, text="Показать дату", command=get_date)

day.grid(row=0, column=0, padx=5, pady=5)
month.grid(row=0, column=1, padx=5, pady=5)
year.grid(row=0, column=2, padx=5, pady=5)
btn.grid(row=1, column=0, columnspan=3, pady=5)

root.mainloop()
Результат: три спинбокса рядом, кнопка выводит выбранную дату в консоль.

Пример 4: Создание виджета для ввода пароля с маскировкой

Виджет Entry позволяет скрывать вводимые символы с помощью параметра show.

Пример

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()
root.title("Вход")

lbl = tk.Label(root, text="Пароль:")
lbl.pack()
entry = tk.Entry(root, show="*", width=20)
entry.pack()

def check_password():
    pwd = entry.get()
    if pwd == "secret":
        messagebox.showinfo("Успех", "Пароль верный")
    else:
        messagebox.showerror("Ошибка", "Неверный пароль")

btn = tk.Button(root, text="Проверить", command=check_password)
btn.pack()

root.mainloop()
Результат: при вводе символов они заменяются звездочками. После нажатия кнопки проверяется пароль.

Пример 5: Динамическое изменение текста метки

Обновляем текст Label при помощи таймера.

Пример

import tkinter as tk
from datetime import datetime

root = tk.Tk()
root.title("Часы")

lbl = tk.Label(root, font=("Arial", 24))
lbl.pack(padx=20, pady=20)

def update_time():
    current_time = datetime.now().strftime("%H:%M:%S")
    lbl.config(text=current_time)
    root.after(1000, update_time)  # вызываем каждую секунду

update_time()
root.mainloop()
Результат: метка отображает текущее время, обновление каждую секунду.

Пример 6: Использование Text для отображения лога с автоскроллом

Добавляем текст в конец и прокручиваем вниз.

Пример

import tkinter as tk
from tkinter import scrolledtext
import random

root = tk.Tk()
root.title("Лог")

log = scrolledtext.ScrolledText(root, width=50, height=10)
log.pack()

def add_log():
    line = f"[{random.randint(1,100)}] Событие произошло\n"
    log.insert(tk.END, line)
    log.see(tk.END)  # прокрутить вниз
    root.after(2000, add_log)  # повтор через 2 секунды

add_log()
root.mainloop()
Результат: в окно каждые 2 секунды добавляется новая строка, полоса прокрутки автоматически смещается вниз.

Текстовые элементы в tkinter - comments

En
Python tkinter текст (python)