Text – многострочное текстовое поле

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

В tkinter многострочное текстовое поле создается от класса Text. По умолчанию его размер равен 80-ти знакоместам по горизонтали и 24-м по вертикали.

Размер текстового поля

Однако эти свойства можно изменять с помощью опций width и height. Есть возможность конфигурировать шрифт, цвета и другое.

from tkinter import *
root = Tk()
 
text = Text(width=25, height=5, bg="darkgreen", fg='white', wrap=WORD)
 
text.pack()
root.mainloop()

Свойства виджета Text

Значение WORD опции wrap позволяет переносить слова на новую строку целиком, а не по буквам.

Text и Scrollbar

Если в текстовое поле вводится больше линий текста, чем его высота, то оно само будет прокручиваться вниз. При просмотре прокручивать вверх-вниз можно с помощью колеса мыши и стрелками на клавиатуре. Однако бывает удобнее пользоваться скроллером – полосой прокрутки.

В tkinter скроллеры производятся от класса Scrollbar. Объект-скроллер связывают с виджетом, которому он требуется. Это не обязательно многострочное текстовое поле. Часто полосы прокрутки бывают нужны спискам, которые будут рассмотрены позже.

from tkinter import *
root = Tk()
 
text = Text(width=20, height=7)
text.pack(side=LEFT)
 
scroll = Scrollbar(command=text.yview)
scroll.pack(side=LEFT, fill=Y)
 
text.config(yscrollcommand=scroll.set)
 
root.mainloop()

Text и Scrollbar

Здесь создается скроллер, к которому с помощью опции command привязывается прокрутка текстового поля по оси ytext.yview. В свою очередь текстовому полю опцией yscrollcommand устанавливается ранее созданный скроллер – scroll.set.

Методы Text

Основные методы у Text такие же как у Entry – get(), insert(), delete(). Однако, если в случае однострочного текстового поля было достаточно указать один индекс элемента при вставке или удалении, то в случае многострочного надо указывать два – номер строки и номер символа в этой строке (другими словами, номер столбца). При этом нумерация строк начинается с единицы, а столбцов – с нуля.

from tkinter import *
 
def insertText():
    s = "Hello World"
    text.insert(1.0, s)
 
def getText():
    s = text.get(1.0, END)
    label['text'] = s
 
def deleteText():
    text.delete(1.0, END)
 
root = Tk()
 
text = Text(width=25, height=5)
text.pack()
 
frame = Frame()
frame.pack()
 
b_insert = Button(frame, text="Вставить", command=insertText)
b_insert.pack(side=LEFT)
 
b_get = Button(frame, text="Взять", command=getText)
b_get.pack(side=LEFT)
 
b_delete = Button(frame, text="Удалить", command=deleteText)
b_delete.pack(side=LEFT)
 
label = Label()
label.pack()
 
root.mainloop()

Методы текстового поля

Методы get() и delete() могут принимать не два, а один аргумент. В таком случае будет обрабатываться только один символ в указанной позиции.

Теги

Особенностью текстового поля библиотеки Tk является возможность форматировать текст в нем, то есть придавать его разным частям разное оформление. Делается это с помощью методов tag_add() и tag_config(). Первый добавляет тег, при этом надо указать его произвольное имя и отрезок текста, к которому он будет применяться. Метод tag_config() настраивает тегу стили оформления.

from tkinter import *
root = Tk()
 
text = Text(width=50, height=10)
text.pack()
text.insert(1.0, "Hello world!\nline two")
 
text.tag_add('title', 1.0, '1.end')
text.tag_config('title', font=("Verdana", 24, 'bold'), justify=CENTER)
 
root.mainloop()

Добавление тегов

Вставка виджетов в текстовое поле

В Text можно вставлять другие виджеты помощью метода window_creat(). Потребность в этом не велика, однако может быть интересна с объектами типа Canvas. Данный класс будет изучен позже. В примере ниже вставляется метка в текущую (INSERT) позицию курсора.

from tkinter import *
 
def smile():
    label = Label(text=":)", bg="yellow")
    text.window_create(INSERT, window=label)
 
root = Tk()
 
text = Text(width=50, height=10)
text.pack()
 
button = Button(text=":)", command=smile)
button.pack()
 
root.mainloop()

Метод window_create()

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

Практическая работа

Напишите программу, состоящую из однострочного и многострочного текстовых полей и двух кнопок "Открыть" и "Сохранить". При клике на первую должен открываться на чтение файл, чье имя указано в поле класса Entry, а содержимое файла должно загружаться в поле типа Text.

При клике на вторую кнопку текст, введенный пользователем в экземпляр Text, должен сохраняться в файле под именем, которое пользователь указал в однострочном текстовом поле.

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

Для выполнения практической работы вам понадобится функция open() языка Python и методы файловых объектов чтения и записи. Освежить знания о них можно здесь.

Пример приложения Tkinter

Курс с примерами решений практических работ: android-приложение, pdf-версия.

Создано

Обновлено

Комментарии

Ответ на от Alex

from tkinter import *
 
root = Tk()
 
img = PhotoImage(file='smile.gif')
txt = Text(width=20, height=10)
txt.image_create(1.0,image=img)
txt.pack()
 
root.mainloop()

В параметре file экземпляра PhotoImage указывается адрес к файлу. Раньше поддерживался только gif и еще один формат. Сейчас возможно больше.

from tkinter import*
import pickle
root = Tk()
root.title('Txt file opener')#Название окна
#Создаем три фрэйма, чтобы упорядочить виджеты
#f_1 = Frame(root, width=200, height=200)
f_2 = Frame(root, width=200, height=200)
f_3 = Frame(root, width=200, height=200)
#f_1.pack(side=BOTTOM, anchor=W)
f_2.pack(side=BOTTOM, anchor=W)
f_3.pack(side=BOTTOM, anchor=W)
#Поле ввода имени файла
entry = Entry(f_3, width=30)
entry.pack(side=LEFT, padx=5, pady=10, anchor=W)
#Поле, где появляется текст
text_1 = Text(f_2)
text_1.pack(side=LEFT)
 
scroll_1 = Scrollbar(f_2, command=text_1.yview)
scroll_1.pack(side=LEFT, fill=Y)
 
text_1.config(yscrollcommand=scroll_1.set)
 
'''scroll_2 = Scrollbar(f_2, command=text_1.xview)
scroll_2.pack(side=BOTTOM)
#не работает по оси икс второй скроллбар( что делать?
text_1.config(xscrollcommand=scroll_2.set)'''
 
def open_file():
    text_1.delete(1.0, END)
    for i in open(entry.get(), encoding='UTF-8'):
        text_1.insert(END, i)
def save_file():
    get = text_1.get(1.0, END)
    file = open(entry.get(), encoding='UTF-8', mode='w')
    file.write(str(get))
    file.close()
but_1 = Button(f_3,
               width=20,
               text='Открыть',
               command=open_file)
but_2 = Button(f_3,
               text='Сохранить',
               width=20,
               command=save_file)
but_1.pack(side=LEFT)
but_2.pack(side=LEFT, padx=5)
 
 
 
mainloop()