Правильный ответ: используйте атрибут validatecommand
виджета. К сожалению, эта функция сильно недооценена в мире Tkinter, хотя она достаточно хорошо документирована в мире Tk. Несмотря на то, что он не задокументирован хорошо, он имеет все необходимое для проверки, не прибегая к привязкам или отслеживанию переменных, или изменяя виджет из процедуры проверки.
Фокус в том, чтобы знать, что вы можете передавать Tkinter специальными значениями в свою команду проверки. Эти значения дают вам всю необходимую информацию, чтобы определить, действительны ли данные или нет: значение до редактирования, значение после редактирования, если редактирование действительно, и несколько других бит информации. Однако для их использования вам нужно сделать немного вуду, чтобы передать эту информацию вашей команде проверки.
Примечание: важно, чтобы команда проверки возвращала либо True
, либо False
. Все остальное приведет к отключению проверки для виджета.
Вот пример, который позволяет только в нижнем регистре (и печатает все эти напуганные значения):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# 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
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:\n")
self.text.insert("end","d='%s'\n" % d)
self.text.insert("end","i='%s'\n" % i)
self.text.insert("end","P='%s'\n" % P)
self.text.insert("end","s='%s'\n" % s)
self.text.insert("end","S='%s'\n" % S)
self.text.insert("end","v='%s'\n" % v)
self.text.insert("end","V='%s'\n" % V)
self.text.insert("end","W='%s'\n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Это правильный способ сделать это.Он рассматривает проблемы, которые я обнаружил, когда пытался получить ответ jmeyer10. Этот один пример обеспечивает превосходную документацию для проверки по сравнению с тем, что я могу найти в другом месте. Хотел бы я дать эти 5 голосов. –
WOW! Я согласен с Стивеном - это тот тип ответа, который заслуживает более одного голоса. Вы должны написать книгу о Tkinter (и вы уже опубликовали достаточно решений, чтобы сделать многотомную серию). Спасибо!!! – Malcolm
В качестве побочного примечания: Я взорван силой Ткинтера. В течение многих лет он получил плохую упаковку, но с новой поддержкой родных тем (ttk) и объяснением своих скрытых полномочий силами таких экспертов, как Брайан Оукли, эта инфраструктура графического интерфейса может иметь свои собственные против подобных wxPython, pyQT и других , – Malcolm