Валидация Tkinter в Python: параметры и примеры
Рассмотрим, как использовать валидацию Tkinter для проверки введенных пользователем данных в Python.
Что такое валидация Tkinter
Проверка (валидация) Tkinter основана на трех параметрах, которые можно использовать для любого виджета ввода, например виджета Entry:
- validate: указывает, какой тип события вызовет проверку.
- validatecommand: проверяет, являются ли данные действительными
- invalidcommand: выполняется, когда данные недействительны. Другими словами, он будет выполнен, если validatecommand вернет False.
validate
Команда validate может иметь одно из следующих строковых значений:
‘focus’ | Проверять каждый раз, когда виджет получает или теряет фокус. |
‘focusin’ | Проверять каждый раз, когда виджет получает фокус. |
‘focusout’ | Проверять каждый раз, когда виджет теряет фокус. |
‘key’ | Проверять, когда нажатие клавиши изменяет содержимое виджета. |
‘all’ | Проверьте во всех вышеперечисленных ситуациях focusing, focusout и key |
‘none’ | Отключить проверку. Это значение по умолчанию. Обратите внимание, что строка ‘none’ не является значением None в Python. |
validatecommand
Команда validatecommand — это кортеж, содержащий:
- Ссылка на функцию Tcl/tk.
- Ноль или более кодов подстановки указывают информацию, которая запускает событие, которое вы хотите передать в функцию.
Чтобы получить ссылку на функцию Tck/tk, вы передаете вызываемый метод widget.register(). Он возвращает строку, которую можно использовать с командой validatecommand.
В следующей таблице показаны коды подстановки, которые можно использовать с кортежем:
%d’ | Код действия: 0 для попытки удаления, 1 для попытки вставки или -1, если обратный вызов был вызван для установки фокуса, снятия фокуса или изменения текстовой переменной. |
‘%i’ | Когда пользователь пытается вставить или удалить текст, этот аргумент будет индексом начала вставки или удаления. Если обратный вызов был вызван focusing, focusout или изменением textvariable, аргумент будет равен -1. |
‘%P’ | Значение, которое будет иметь текст, если изменение разрешено. |
‘%s’ | Текст в записи до изменения. |
‘%S’ | Если вызов был вызван вставкой или удалением, этим аргументом будет текст, который вставляется или удаляется. |
‘%v’ | Текущее значение параметра проверки виджета. |
‘%V’ | Причина этого обратного вызова: одна из следующих: «focusin», «focusout», «key» или «forced», если textvariable была изменена. |
‘%W’ | Название виджета. |
В следующем примере создается команда validatecommand, которая использует метод self.validate() и код подстановки %P:
vcmd =(self.register(self.validate), '%P')
invalidcommand
Как и команда validatecommand, команда invalidcommand также требует использования метода widget.register() и кода подстановки.
Следующий пример возвращает кортеж, который можно передать в параметр invalidcommand:
ivcmd =(self.register(self.on_invalid),)
Пример валидации Tkinter
Мы создадим форму, содержащую поле ввода адреса электронной почты. Если вы введете недействительный адрес электронной почты, будет показано сообщение об ошибке и цвет текста поля ввода адреса электронной почты изменится на красный. И мы запустим событие проверки, когда фокус выйдет за пределы поля.
Вот полная программа:
import tkinter as tk from tkinter import ttk import re class App(tk.Tk): def __init__(self): super().__init__() self.title('Tkinter Validation Demo') self.create_widgets() def create_widgets(self): self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=3) self.columnconfigure(2, weight=1) # label ttk.Label(text='Email:').grid(row=0, column=0, padx=5, pady=5) # email entry vcmd =(self.register(self.validate), '%P') ivcmd =(self.register(self.on_invalid),) self.email_entry = ttk.Entry(self, width=50) self.email_entry.config(validate='focusout', validatecommand=vcmd, invalidcommand=ivcmd) self.email_entry.grid(row=0, column=1, columnspan=2, padx=5) self.label_error = ttk.Label(self, foreground='red') self.label_error.grid(row=1, column=1, sticky=tk.W, padx=5) # button self.send_button = ttk.Button(text='Send').grid(row=0, column=4, padx=5) def show_message(self, error='', color='black'): self.label_error['text'] = error self.email_entry['foreground'] = color def validate(self, value): """ Validat the email entry :param value: :return: """ pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' if re.fullmatch(pattern, value) is None: return False self.show_message() return True def on_invalid(self): """ Show the error message if the data is not valid :return: """ self.show_message('Please enter a valid email', 'red') if __name__ == '__main__': app = App() app.mainloop()
Как это работает.
- Сначала создайте команду проверки, используя метод self.validate() и код подстановки %P:
vcmd =(self.register(self.validate), '%P')
- Во-вторых, создайте invalidatecommand, которая использует метод self.on_invalid:
ivcmd =(self.register(self.on_invalid),)
- В-третьих, настройте виджет ввода, который использует validation, validatecommand и invalidatecommand:
self.email_entry.config(validate='focusout', validatecommand=vcmd, invalidcommand=ivcmd)
- В-четвертых, определите метод show_message(), который изменяет текст виджета label_error и цвет текста виджета email_entry:
def show_message(self, error='', color='black'): self.label_error['text'] = error self.email_entry['foreground'] = color
- В-пятых, определите метод validate(), который проверяет значение email_entry.
def validate(self, value): """ Validat the email entry :param value: :return: """ pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' if re.fullmatch(pattern, value) is None: return False self.show_message() return True
Метод validate() возвращает True, если текст ввода является допустимым, или False в противном случае. Если текст ввода является допустимым адресом электронной почты, вызовите show_message(), чтобы скрыть сообщение об ошибке и установить цвет текста на черный.
Tkinter выполнит метод on_invalid(), если введенный текст не является допустимым адресом электронной почты.
Наконец, определите метод on_invalid(), который отображает сообщение об ошибке, и установите красный цвет текста виджета email_entry.
def on_invalid(self): """ Show the error message if the data is not valid :return: """ self.show_message('Please enter a valid email', 'red')