Работа с текстовыми полями – неотъемлемая составляющая работы с графическими интерфейсами. Почти любая информация, которая требует ввода текста, заносится именно в текстовые элементы. Типичный пример – вы пользовались поисковой строкой в браузере. Вот она и является типичным представителем элемента, предназначенного для ввода текста. Создание текстовых элементов осуществляется с помощью специализированного виджета – Entry. Это один из самых популярных классов в Tkinter по описанным выше причинам.
Создание текстового элемента
Приведем пример, который наглядно показывает, как происходит создание формы логина с двумя текстовыми полями – имя пользователя (username) и пароль (password). В последнем текстовом поле символы будут отображаться в виде звездочек, чтобы другие люди не могли видеть, что содержится в поле для ввода пароля. Соответственно, для этого задается параметр show, который задает знак, которым замещается вводимый человеком текст.
То есть, вместо звездочки можно выбрать любой другой символ, который есть в таблице символов. Например, точку.
Также у программы есть такие элементы:
- Кнопка «Войти». После того, как нажмете на эту кнопку, результат будет выведен в консоль.
- Кнопка «Очистить». Предназначена для того, чтобы убрать все содержимое всех элементов консоли. Фокус же возвращается в username после этого.
Выглядит программа следующим образом.
А чтобы ее реализовать на практике, необходимо использовать такой код. Будем его разбирать потихоньку.
import tkinter as tk
class LoginApp(tk.Tk):
def __init__(self):
super().__init__()
self.username = tk.Entry(self)
self.password = tk.Entry(self, show=»*»)
self.login_btn = tk.Button(self, text=»Войти»,
command=self.print_login)
self.clear_btn = tk.Button(self, text=»Очистить»,
command=self.clear_form)
self.username.pack()
self.password.pack()
self.login_btn.pack(fill=tk.BOTH)
self.clear_btn.pack(fill=tk.BOTH)
def print_login(self):
print(«Логин: {}».format(self.username.get()))
print(«Пароль: {}».format(self.password.get()))
def clear_form(self):
self.username.delete(0, tk.END)
self.password.delete(0, tk.END)
self.username.focus_set()
if __name__ == «__main__»:
app = LoginApp()
app.mainloop()
Принцип работы текстовых виджетов
Создание виджетов осуществляется в родительском окне или фрейме и передаются в качестве первого аргумента. Возможно задание дополнительных характеристик с помощью специальных ключевых слов. В приведенном выше фрагменте кода таких свойств не имеет поле с именем пользователя. А вот у поля ввода пароля таковым является аргумент show, с помощью которого мы сделали так, чтобы каждый введенный пользователем символ превращался в звездочку.
А чтобы текущий текст получить в форме строки, используется метод get(). А с помощью метода print_login() мы вывели содержимое текстового поля в стандартном выводе.
С помощью метода delete() мы удаляли текст. Он принимает два аргумента, позволяющие задавать символы, которые будут удаляться. При этом важно учитывать, что все индексы стартуют с 0, и последний символ в них не включается. Можно передать только один аргумент. В этом случае удаляется символ, который находится на том месте, которое задано.
С помощью метода clear_form() мы удаляем текст, начиная первым индексом и заканчивая константой END. Благодаря этому получается очистить весь контент. Затем фокус перемещается в поле username.
Чтобы изменить содержимое виджета Entry, необходимо использовать метод insert(), которому необходимо передавать два аргумента:
- Место, в которое нужно вставить текст. В качестве первой позиции выступает 0.
- Строка, которую необходимо вставить в текстовое поле.
Учтите, что по умолчанию значение первого индекса – 0.
Таким образом, чтобы сбросить содержимое на то, что задано в текстовом поле по стандарту, необходимо использовать два метода. Сначала – delete(), чтобы удалить содержимое текстового поля, а затем – insert(). Также можно добавлять текст в место нахождения курсора. Для этого используется специализированная константа – INSERT.
Точно так же, как и элемент класса Button, текстовое поле может принимать специальные параметры для изменения внешнего вида контура. Также ему можно задавать определенное состояние. Первая задача реализуется с помощью параметра relief, а вторая – с использованием параметра state.
Если состояние текстового поля установлено как disabled или readonly, то ни один метод, изменяющий его содержимое, не будет работать. То есть, использовать методы delete() и insert() невозможно.
Изменения текста: как отслеживать?
А что, если, допустим, понадобится восстановить текст, если в нем изменится содержимое. Или же создать текстовое поле, которое удаляет весь текст, если в нем ввести определенное значение. Для этого необходимо отслеживать изменение текста. Эта задача реализуется с помощью параметра textvariable. Чтобы отследить запись, необходимо использовать функцию обратного вызова show_message().
Работает это приблизительно так.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.var = tk.StringVar()
self.var.trace(«w», self.show_message)
self.entry = tk.Entry(self, textvariable=self.var)
self.btn = tk.Button(self, text=»Очистить»,
command=lambda: self.var.set(«»))
self.label = tk.Label(self)
self.entry.pack()
self.btn.pack()
self.label.pack()
def show_message(self, *args):
value = self.var.get()
text = «Привет, {}!».format(value) if value else «»
self.label.config(text=text)
if __name__ == «__main__»:
app = App()
app.mainloop()
Если в текстовое поле вводится какая-то информация, то в этом примере текст в окне изменяется в зависимости от того, что вводится в текстовое поле. Допустим, если ввести в элемент класса Entry «Мир», то в ответ будет выдано сообщение «Привет, Мир», и так далее.
Принцип изменения текста
Первые несколько строк конструктора приложения генерируют объект StringVar и связывают функцию обратного вызова с ним. Есть несколько режимов, которые могут быть:
- Если переменная записывается, активируется режим w.
- Если переменная читается, активируется режим r.
- Если переменная удаляется, активируется режим u.
Когда пользователь вызывает функцию обратного вызова, она получает три аргумента. Первый – это внутреннее имя переменной. Второй – это пустая строка. Третий – это режим, запустивший операцию. Тем не менее, эти аргументы могут стать необязательными, если использовать *args.
Если необходимо получить значение переменной, актуальное на данный момент, используется метод get(). А чтобы изменить его, используется метод set(). Также все методы прослушки trace уведомляются ими. Поэтому после того, как человек редактирует текст в поле ввода или нажимает кнопку «Очистить», запускается метод show_message().
Что касается переменных Tk, то они также опциональные. Тем не менее, их обязательно нужно использовать в классах Checkbutton и Radiobutton.
Валидация текста
Есть определенные правила, которым некоторые поля должны соответствовать. Например, длина строки не должна быть больше заданного значения. Множество приложений предусматривают валидацию уже после того, как пользователь ввел данные. Тем не менее, значительно удобнее интегрировать проверку непосредственно в текстовую строку.
Иногда необходимо не допустить ввод содержимого, не соответствующего требованиям. Рассмотрим, как это делается, на практике.
Валидация текста
Самый лучший способ валидации текста – использовать регулярные выражения. Приведем пример, как это работает.
import re
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.pattern = re.compile(«^\w{0,10}$»)
self.label = tk.Label(self, text=»Введите логин»)
vcmd = (self.register(self.validate_username), «%i», «%P»)
self.entry = tk.Entry(self, validate=»key»,
validatecommand=vcmd,
invalidcommand=self.print_error)
self.label.pack()
self.entry.pack(anchor=tk.W, padx=10, pady=10)
def validate_username(self, index, username):
print(«Проверка символа» + index)
return self.pattern.match(username) is not None
def print_error(self):
print(«Запрещенный символ в логине»)
if __name__ == «__main__»:
app = App()
app.mainloop()
Если попробовать выполнить этот фрагмент кода, будет выдана ошибка, если пользователь не укажет ни одной буквы или цифры. Если же пользователь вводит строку длиной больше 10 символов, то также будет выдаваться исключение. Все потому, что мы ограничили общее количество символов с помощью регулярного выражения.
Особенности валидации текста
Валидация задается параметром validate. Правила задаются с помощью значения этого параметра. Например, если использовать key в качестве значения этого параметра, то при каждом изменении содержимого будет осуществляться валидация.
Если использовать значение none (которое действует, если не задано обратное), то валидация не будет осуществляться.
Кроме этого, в качестве значений могут выступать focusin или focusout. В первом случае валидация будет осуществляться исключительно при получении текстовым полем фокуса. Во втором же – при его потере.
Вопрос: как же сделать, чтобы валидация осуществлялась во всех случаях? В этом случае необходимо установить значение all.
Таким образом, Python предоставляет широкие возможности для работы с текстом в графической библиотеке Tkinter.