Interactively validating Entry widget content in tkinter
Интерактивная проверка содержимого виджета ввода в tkinter
Какой рекомендуемый метод интерактивной проверки содержимого в виджете tkinter Entry?
Я прочитал сообщения об использовании validate=True и validatecommand=command, и, похоже, что эти функции ограничены тем фактом, что они очищаются, если validatecommand команда обновляет Entry значение виджета.
Учитывая такое поведение, должны ли мы привязываться к событиям KeyPress, Cut и Paste и отслеживать / обновлять значение нашего Entry виджета с помощью этих событий? (И другие связанные события, которые я, возможно, пропустил?)
Или нам следует вообще забыть об интерактивной проверке и проверять только по FocusOut событиям?
Переведено автоматически
Ответ 1
Правильный ответ: используйте validatecommand атрибут виджета. К сожалению, эта функция сильно недооценивается в мире Tkinter, хотя она вполне достаточно документирована в мире Tk. Несмотря на то, что он плохо документирован, в нем есть все необходимое для проверки, не прибегая к привязкам или трассировке переменных, или модификации виджета в рамках процедуры проверки.
Хитрость заключается в том, чтобы знать, что вы можете попросить Tkinter передать специальные значения вашей команде validate. Эти значения предоставляют вам всю информацию, которую вам нужно знать, чтобы решить, являются ли данные допустимыми или нет: значение до редактирования, значение после редактирования, если редактирование допустимо, и несколько других битов информации. Однако, чтобы использовать их, вам нужно проделать небольшую хитрость, чтобы передать эту информацию вашей команде validate.
Примечание: важно, чтобы команда проверки возвращала либо True, либо False. Все остальное приведет к отключению проверки для виджета.
Вот пример, который допускает использование только нижнего регистра. Он также выводит значения всех специальных значений для иллюстративных целей. Они не все необходимы; вам редко требуется больше одного или двух.
import tkinter as tk # python 3.x # import Tkinter as tk # python 2.x
# valid percent substitutions (from the Tk entry man page) # note: you only have to register the ones you need; this # example registers them all for illustrative purposes # # %d = Type of action (1=insert, 0=delete, -1 for others) # %i = index of char string to be inserted/deleted, or -1 # %P = value of the entry if the edit is allowed # %s = value of entry prior to editing # %S = the text string being inserted or deleted, if any # %v = the type of validation that is currently set # %V = the type of validation that triggered the callback # (key, focusin, focusout, forced) # %W = the tk name of the widget
После изучения и экспериментов с кодом Брайана я создал минимальную версию проверки ввода. Следующий код будет отображать поле ввода и принимать только цифровые цифры.
from tkinter import *
root = Tk()
deftestVal(inStr,acttyp): if acttyp == '1': #insert ifnot inStr.isdigit(): returnFalse returnTrue
Текст копируется / вставляется в случае неработающей ссылки
Виджет ввода также поддерживает опцию invalidcommand, которая определяет функцию обратного вызова, которая вызывается всякий раз, когда validatecommand возвращает False. Эта команда может изменять текст в виджете с помощью метода .set() для связанной с виджетом текстовой переменной. Настройка этой опции работает так же, как настройка validatecommand . Вы должны использовать метод .register() для переноса вашей функции Python; этот метод возвращает имя обернутой функции в виде строки. Затем вы передадите в качестве значения параметра invalidcommand либо эту строку, либо как первый элемент кортежа, содержащего коды подстановки.
Примечание: Есть только одна вещь, которую я не могу понять, как это сделать: если вы добавляете проверку к записи, а пользователь выбирает часть текста и вводит новое значение, нет способа зафиксировать исходное значение и сбросить запись. Вот пример
Entry предназначен для приема только целых чисел за счет реализации 'validatecommand'
Пользователь вводит 1234567
Пользователь выбирает '345' и нажимает 'j'. Это регистрируется как два действия: удаление '345' и вставка 'j'. Tkinter игнорирует удаление и выполняет только вставку 'j'. 'validatecommand' возвращает значение False, а функции 'invalidcommand' передаются следующие значения: %d= 1, %i= 2, %P = 12j67, %s = 1267, %S= j
Если код не реализует функцию 'invalidcommand', функция 'validatecommand' отклонит 'j', и результатом будет 1267. Если в коде действительно реализована функция 'invalidcommand', восстановить исходную 1234567 невозможно.