Как очистить tk.Entry
Я видел способ entry.delete(0, ‘end’) но мне почему то постоянно пишет _tkinter.TclError: bad text index «1» и не важно что я туда напишу. Любой другой индекс или к примеру ‘first’ он всегда выдаёт эту ошибку
Отслеживать
задан 29 апр 2021 в 9:53
Ежи Сармат Ежи Сармат
97 2 2 серебряных знака 11 11 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
bad text index «1»
говорит о том, что у вас не Entry а Text (для Entry аналогичная ошибка звучит как bad entry index «1.0» ).
Для Text индексы должны быть формата номер_строки.номер_колонки (причем номер строки считается с 1, а номер колонки с 0) — в виде числа с плавающей точкой, например 1.0 (но не целого числа 1), или в виде строки «1.0» .
from tkinter import * root = Tk() entry = Entry() entry.pack() def clear_entry(): entry.delete(0, END) # Удалить все, начиная с 0-го символа до конца Button(text="Clear Entry", command=clear_entry).pack() text = Text() text.pack() def clear_text(): text.delete(1.0, END) # Удалить все, начиная с 0-го символа 1-й строки до конца Button(text="Clear Text", command=clear_text).pack() root.mainloop()
Как очистить поле entry в tkinter
Элемент Entry представляет поле для ввода текста. С помощью конструктора Entry можно установить ряд параметров, основные из них:
- background : фоновый цвет
- cursor : курсор указателя мыши при наведении на текстовое поле
- foreground : цвет текста
- font : шрифт текста
- justify : устанавливает выравнивание текста. Значение LEFT выравнивает текст по левому краю, CENTER — по центру, RIGHT — по правому краю
- show : задает маску для вводимых символов
- state : состояние элемента, может принимать значения NORMAL (по умолчанию) и DISABLED
- textvariable : устанавливает привязку к элементу StringVar
- width : ширина элемента
Элемент Entry имеет ряд методов. Основные из них:
- insert(index, str) : вставляет в текстовое поле строку по определенному индексу
- get() : возвращает введенный в текстовое поле текст
- delete(first, last=None) : удаляет символ по индексу first. Если указан параметр last, то удаление производится до индекса last. Чтобы удалить до конца, в качестве второго параметра можно использовать значение END.
- focus() : установить фокус на текстовое поле
Простейшее текстовое поле:
from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") ttk.Entry().pack(anchor=NW, padx=8, pady= 8) root.mainloop()
Получение введенного текста
Для получения текста из Entry, можно использовать его метод get() . Так, определим элемент Entry и по нажатию на кнопку выведем введенный текст на текстовую метку:
from tkinter import * from tkinter import ttk def show_message(): label["text"] = entry.get() # получаем введенный текст root = Tk() root.title("METANIT.COM") root.geometry("250x200") entry = ttk.Entry() entry.pack(anchor=NW, padx=6, pady=6) btn = ttk.Button(text="Click", command=show_message) btn.pack(anchor=NW, padx=6, pady=6) label = ttk.Label() label.pack(anchor=NW, padx=6, pady=6) root.mainloop()
Вставка и удаление текста
Рассмотрим вставку и удаление текста в Entry:
from tkinter import * from tkinter import ttk def clear(): entry.delete(0, END) # удаление введенного текста def display(): label["text"] = entry.get() # получение введенного текста root = Tk() root.title("METANIT.COM") root.geometry("250x150") label = ttk.Label() label.pack(anchor=NW, padx=6, pady=6) entry = ttk.Entry() entry.pack(anchor=NW, padx=6, pady=6) # вставка начальных данных entry.insert(0, "Hello World") display_button = ttk.Button(text="Display", command=display) display_button.pack(side=LEFT, anchor=N, padx=6, pady=6) clear_button = ttk.Button(text="Clear", command=clear) clear_button.pack(side=LEFT, anchor=N, padx=6, pady=6) root.mainloop()
При запуске программы в текстовое поле сразу же добавляется текст по умолчанию:
entry.insert(0, "Hello World")
Кнопка Clear очищает оба поля, вызывая метод delete:
def clear(): entry.delete(0, END)
Вторая кнопка, используя метод get, получает введенный текст:
def display(): label["text"] = entry.get()
Валидация
С помощью параметра validate конструктора Entry можно задать, когда проводить валидацию введенного значения. Этот параметр может принимать следующие значения:
- none : отсутствие валидации, значение по умолчанию
- focus : валидация при получении фокуса
- focusin : валидация при изменении фокуса
- focusout : валидация при потере фокуса
- key : валидация при каждом вводе нового символа
- all : валидация при измении фокуса и вводе символов в поле
Параметр validatecommand позволяет установить команду валидации.
Рассмотрим небольшой пример. Допустим, пользовтаель должен ввести номер телефона в формете +xxxxxxxxxxx. То есть сначала должен идти знак +, а затем 11 цифр, например, +12345678901:
from tkinter import * from tkinter import ttk import re def is_valid(newval): return re.match("^\+\d$", newval) is not None root = Tk() root.title("METANIT.COM") root.geometry("250x200") check = (root.register(is_valid), "%P") phone_entry = ttk.Entry(validate="key", validatecommand=check) phone_entry.pack(padx=5, pady=5, anchor=NW) root.mainloop()
Итак, параметр validate=»key» указывает, что мы будем валидировать ввод при каждом нажати на клавиатуру. Параметр validatecommand=check говорит, что валидировать ввод будет команда «check». Эта команда представляет кортеж из двух элементов:
check = (root.register(is_valid), "%P")
Первый элемент — вызов метода root.register(is_valid) регистрирует функцию, которая собственно будет производить валидацию — это функция is_valid() . Второй элемент — подстановка «%P» представляет новое значение, которое передается в функцию валидации.
Собственно саму валидацию выполняет функция is_valid() . Она принимает один параметр — текущее значение Entry, которое надо валидировать. Она возвращает True, если значение прошло валидацию, и False, если не прошло. Сама логика валидации представляет проверку строки на регулярное выражение «^\+\d*$» . Если новое значение соответствует этому выражению, и в нем не больше 12 символов, то оно прошло валидацию.
В итоге мы сможем ввести в текстовое поле только символ + и затем только 11 цифр.
Теперь немного изменим код и добавим вывод ошибок валидации:
from tkinter import * from tkinter import ttk import re def is_valid(newval): result= re.match("^\+\d$", newval) is not None if not result and len(newval)Здесь для вывода ошибок валидации добавлен виджет Label. Если введенное значение не соответствует регулярному выражению (например, пользователь попытался ввести нецифровой символ), и длина ввода меньше и равно 12 символов (проверять ввод больше 12 символов нет смысла, так как номер телефона содержит только 12 символов), то в метке выводим сообщение об ошибке
Также мы можем передать значение параметра validate, чтобы в функции валидации в зависимости от того, нажал пользователь на клавишу или убрал фокус с поля, производить те или иные действия. В этом случае необходимо передать команде валидации дополнительный аргумент:
check = (root.register(is_valid), "%P", "%V")Здесь значение "%V" представляет событие, которое вызывает валидацию (focus/focusin/focusout/key). Тогда в функции валидации с помощью второго параметра мы сможем получить это значение:
def is_valid(newval, op): result= re.match("^\+\d$", newval) is not None if op=="key": # некоторые действия elif op=="focus": # некоторые действия return resultСоздание, изменение и проверка текста / tkinter 2
Виджет Entry представляет собой текстовый элемент на одной строке. Вместе с классами Label и Button он является одним из самых используемых в Tkinter.
Как создать текстовый элемент
Следующий пример демонстрирует, как создать форму логина с двумя экземплярами для полей username и password . Каждый символ password отображается в качестве звездочки. Кнопка Войти выводит значения в консоли, а Очистить — удаляет содержимое обоих полей, возвращая фокус в 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()Как работают экземпляры
Экземпляры виджетов Entry создаются в родительском окне или фрейме, будучи переданными в качестве первого аргумента. С помощью опциональных ключевых слов можно задать дополнительные свойства. У username в этом примере таких нет, а у password — аргумент show со строкой «*», который будет выводить каждый символ как звездочку.
С помощью метода get() текущий текст можно будет получить в виде строки. Это используется в методе print_login() , который выводит содержимое Entry в стандартном выводе ( stdout ).
Метод delete() принимает два аргумента, которые представляют собой диапазон символов для удаления. Важно только помнить, что индексы начинаются с 0 и не включают последний символ. Если передать только один аргумент, то удалится символ на этой позиции.
В методе clear_form() удаляется содержимое от индекса 0 до константы END , в результате чего весь контент очищается. После этого фокус возвращается в поле username .
Содержимое виджета Entry можно модифицировать с помощью метода insert() , который принимает два аргумента:
- index — позиция, куда нужно вставить текст (индекс первого — 0)
- string — строка, которая будет вставлена
Стандартный шаблон сброса содержимого на значение по умолчанию — комбинация методов delete() и insert() :
Еще один паттерн — добавление текста туда, где находится курсор. Для этого используется константа INSERT :
Как и Button класс Entry также принимает параметры relief и state для изменения стиля контура и состояния. Также стоит отметить, что вызовы delete() и insert() игнорируются, когда состояние равно «disabled» или «readonly».
Отслеживание изменений текста
Переменные Tk позволяют отправлять уведомления приложениям, когда входящие значения меняются. Есть 4 класса переменных в Tkinter: BooleanVar , DoubleVar , IntVar и StringVar . Каждый из них оборачивает значение соответствующего типа Python, который должен соответствовать типу виджета, прикрепленного к переменной.
Эта особенность особенно полезна в том случае, если нужно автоматически обновить отдельные части приложения на основе текущего состояния виджетов.
Как отслеживать изменения текста
В следующем примере экземпляр StringVar ассоциирован с Entry, у которого есть параметр 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()Когда что-то вводится в этот виджет, текст метки обновляется на тот, что был составлен с помощью значения переменной Tk . Например, если ввести слово «Мир», то метка выведет Привет, Мир! . Если текст не вводить совсем, то ничего и не будет выводиться. Для демонстрации возможностей интерактивной настройки содержимого переменной была добавлена кнопка, которая очищает поле по нажатию.
Как работает изменение текста
Первые строки конструктора приложения создают экземпляр StringVar и прикрепляют функцию обратного вызова для режима записи. Валидные значения этого режима:
- w — вызывается, когда переменная пишется
- r — вызывается, когда переменная читается
- u (от unset) — вызывается, когда переменная удаляется
При вызове функция обратного вызова получает три аргумента: внутреннее имя переменной, пустую строку (она используется в других типах переменных Tk ) и режим, который запустил операцию. При объявлении его с *args эти аргументы становятся опциональными, потому что при обратном вызове значения уже не используются.
Метод get() оберток Tk возвращает текущее значение переменной, а метод set() — обновляет его. Они также уведомляют все методы прослушки ( trace ). Поэтому изменение содержимого поля с помощью графического интерфейса и нажатие кнопки Очистить запускают вызов метода show_message() .
Переменные Tk являются опциональными для виджетов поля, но они обязательны для работы других классов виджетов, таких как классы Checkbutton и Radiobutton .
Валидация текста в полях
Чаще всего поля для ввода текста представляют собой поля, которые следуют определенным правилам валидации, например, максимальная длина или определенный формат. Некоторые приложения предоставляют возможность ввода содержимого любого вида и выполняют валидацию уже после того как вся форма целиком была отправлена.
При определенных условиях нужно предотвратить возможность ввода невалидного содержимого в поле текста. Следующие примеры рассмотрят, как реализовать такое поведение с помощью параметров валидации в виджете Entry.
Как валидировать текст
Следующее приложение демонстрирует, как валидировать текст в поле ввода с помощью регулярных выражений:
import re
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.pattern = re.compile("^\w$")
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 , когда валидация выполняется при получении или потере фокуса. Значение focus выполняет проверку в обоих случаях. Во всех ситуациях валидация проходит, если установить значение all .
Функция validatecommand вызывается каждый раз при запуске валидации. Она должна возвращать true , если введенное содержимое прошло проверку. В противном случае — false .
Поскольку нужно больше информации, чтобы определить, является ли контент валидным, над функцией Python создается обертка Tcl с помощью метода register класса Widget . Затем добавляется замещение для каждого параметра, который будет передаться в функцию. В итоге эти значения группируются в кортеж. Описанное соответствует следующей строке из примера:
vcmd = (self.register(self.validate_username), "%i", "%P")
Можно использовать следующие замещения:
- %d — тип действия. 1 — добавление, 0 — удаление, -1 — остальное;
- %i — индекс вставляемой или удаляемой строки;
- %p — сущность содержимого, если изменение разрешено;
- %s — строковое содержимое до изменения;
- %s — строка, которая вставляется или удаляется;
- %v — тип текущей валидации;
- %V— тип валидации, которая запускает действие;
- %w — название виджета Entry.
Параметр invalidcommand принимает функцию, которая вызывается, когда validatecommand возвращает false . Те же замещения могут быть применены и к нему, но в данном примере классу был прямо передан метод print_error() .
Документация Tcl/Tk предполагает, что не нужно смешивать параметры validatecommand и textvariable , поскольку невалидое значение переменной Tk вообще отключит проверку. То же самое произойдет, если функция validatecommand не вернет булевое значение.
Как очистить поле ввода в Tkinter?
Здравствуйте, нужна помощь. Изучаю Python и решил написать небольшую программу, чтобы немного разобраться во всем.
- Получать данные от пользователя и вносить их в файл.
- При запросе пользователя прочитать файл и вывести данные в табличном виде.
- Удалить ненужные данные (ошибка или потеря актуальности).
Изначально попробовал написать чисто консольный скрипт, теперь хочу добавить немного "красивостей". Использую для этого Tkinter.
На данном этапе готова функция с получением данных и записью в файл. Также есть функция прочтения и вывода в табличной форме (только в консоли, пока не придумал как их вывести в окно программы). Сейчас это весь готовый функционал.
Проблема заключается в следующем: пользователь вводит данные, нажимает кнопку, всё отлично записывается и выскакивает уведомление, дальше нужно очистить поля и ждать следующего действия пользователя.
Почитал про то, как можно очистить поле ввода, перепробовал несколько вариантов, но не один не сработал. Кто может подсказать как это исправить?
Если будут какие-то замечания по коду, пишите в комментариях.
from tkinter import * from tkinter import messagebox import pandas as pd import os def clear (): NameUserEntry.delete("0", END) NumbersEntry.delete("0", END) CarEntry.delete("0", END) VolumeSEntry.delete("0", END) PriceSEntry.delete("0", END) VolumeFEntry.delete("0", END) PriceFEntry.delete("0", END) ExpensesEntry.delete("0", END) def data_user(): os.system('CLS') print("Получение данных. ", end="") name_driver = NameUserEntry.get() number_driver = NumbersEntry.get() car_driver = CarEntry.get() volume_start = int(VolumeSEntry.get()) price_start = int(PriceSEntry.get()) volume_finish = int(VolumeFEntry.get()) price_finish = int(PriceFEntry.get()) expenses = int(ExpensesEntry.get()) profit = volume_finish * price_finish - volume_start * price_start - expenses print('Ок') os.system('CLS') print("Формируется словарь. ", end="") data_driver = < 'name':name_driver, 'numbers':number_driver, 'car':car_driver, 'Vs':volume_start, 'Ps':price_start, 'Vf':volume_finish, 'Pf':price_finish, 'Ex':expenses, 'Prof':profit, >print("Ок") print("Собираем фрейм. ", end="") columns = ['ФИО', 'Телефон', 'Машина', 'Объем на старте', 'Цена покупки', 'Объем на выходе', 'Цена продажи', 'Затраты', 'Профит',] data = [[data_driver['name'], data_driver['numbers'], data_driver['car'], data_driver['Vs'], data_driver['Ps'], data_driver['Vf'], data_driver['Pf'], data_driver['Ex'], data_driver['Prof'] ]] df = pd.DataFrame(data, columns=columns) print('Ок') print('Делаем запись. ', end='') df.to_csv(r'data.csv', mode='a', sep='/', header=False, index=False, encoding='utf-8') print('Ок') positive = 'Запись успешно добалена!' messagebox.showinfo('Уведомление', positive) def read_data(): df =pd.read_csv(r'data.csv', sep='/', names = ['ФИО', 'Телефон', 'Машина', 'Объем на старте', 'Цена покупки', 'Объем на выходе', 'Цена продажи', 'Затраты', 'Профит']) print(df) root = Tk() root.title('F1') root.geometry('500x600') button_padding = header_padding = #ФИО водителя NameUserLabel = Label(root, text='ФИО водителя: ', **header_padding) NameUserLabel.grid(row = 1, rowspan=1, column=1, sticky='w') NameUserEntry = Entry(root, bg='#fff', fg='#444') NameUserEntry.grid(row = 2, rowspan=1, column=1,sticky='w') #Номер телефона NumbersLabel = Label(root, text='Номер телефона: ') NumbersLabel.grid(row = 1, rowspan=1, column=3, sticky='w') NumbersEntry = Entry(root, bg='#fff', fg='#444') NumbersEntry.grid(row = 2, rowspan=1, column=3,sticky='w') #марка машины, номер CarLabel = Label(root, text='Машина(марка,г.с.з.: ', **header_padding) CarLabel.grid(row = 3, rowspan=1, column=1, sticky='w') CarEntry = Entry(root, bg='#fff', fg='#444') CarEntry.grid(row = 4, rowspan=1, column=1,sticky='w') #объем при покупке VolumeSLabel = Label(root, text='Объем (покупка): ', **header_padding) VolumeSLabel.grid(row = 6, rowspan=1, column=1, sticky='w') VolumeSEntry = Entry(root, bg='#fff', fg='#444') VolumeSEntry.grid(row = 7, rowspan=1, column=1,sticky='w') #цена покупки PriceSLabel = Label(root, text='Цена (покупка): ') PriceSLabel.grid(row = 6, rowspan=1, column=3, sticky='w') PriceSEntry = Entry(root, bg='#fff', fg='#444') PriceSEntry.grid(row = 7, rowspan=1, column=3,sticky='w') #объем при продаже VolumeFLabel = Label(root, text='Объем (продажа): ', **header_padding) VolumeFLabel.grid(row = 9, rowspan=1, column=1, sticky='w') VolumeFEntry = Entry(root, bg='#fff', fg='#444') VolumeFEntry.grid(row = 10, rowspan=1, column=1,sticky='w') #цена при продаже PriceFLabel = Label(root, text='Цена (продажа): ') PriceFLabel.grid(row = 9, rowspan=1, column=3, sticky='w',) PriceFEntry = Entry(root, bg='#fff', fg='#444') PriceFEntry.grid(row = 10, rowspan=1, column=3,sticky='w') #прочие затраты ExpensesLabel = Label(root, text='Прочие затраты: ', **header_padding) ExpensesLabel.grid(row = 12, rowspan=1, column=1, sticky='w') ExpensesEntry = Entry(root, bg='#fff', fg='#444', ) ExpensesEntry.grid(row = 13, rowspan=1, column=1,sticky='w') #профит, высчитывается и вносится в таблицу # кнопка сделать запись ButtonWrite = Button(root, text='Сделать запись', bg='#fff', fg='#444') ButtonWrite.grid(row = 15, rowspan=1, column=1, sticky='ws') ButtonWrite.config(command=data_user) # кнопка очистки данных ButtonDelete = Button(root, text='очистить данные', bg='#fff', fg='#444') ButtonDelete.grid(row = 15, rowspan=1, column=3, sticky='w') ButtonDelete.config(command=clear) root.mainloop()
- Вопрос задан более двух лет назад
- 5583 просмотра