tkinter Entry
위젯 에서 대화식으로 콘텐츠를 검증하는 데 권장되는 기술은 무엇입니까 ?
validate=True
및 사용에 대한 게시물을 읽었으며 validatecommand=command
이러한 기능은 validatecommand
명령이 Entry
위젯의 값을 업데이트하면 지워진다는 사실로 인해 제한되는 것으로 보입니다 .
이 동작을 감안할 때, 우리는에 결합한다 KeyPress
, Cut
및 Paste
이벤트 모니터 / 업데이트 우리의 Entry
이러한 이벤트를 통해 위젯의 가치인가? (그리고 내가 놓친 기타 관련 이벤트?)
아니면 대화 형 유효성 검사를 완전히 잊어 버리고 FocusOut
이벤트에 대해서만 유효성을 검사해야 합니까?
답변
정답은 validatecommand
위젯 의 속성을 사용하는 것입니다. 안타깝게도이 기능은 Tkinter 세계에서는 충분히 문서화되어 있지 않지만 Tk 세계에서는 충분히 문서화되어 있습니다. 잘 문서화되어 있지는 않지만 바인딩이나 추적 변수에 의존하지 않고 유효성 검사 절차 내에서 위젯을 수정하지 않고도 유효성 검사를 수행하는 데 필요한 모든 것이 있습니다.
트릭은 Tkinter가 특정 값을 validate 명령에 전달할 수 있다는 것을 아는 것입니다. 이러한 값은 데이터가 유효한지 여부를 결정하는 데 필요한 모든 정보를 제공합니다. 편집 전 값, 편집이 유효한 경우 편집 후 값 및 기타 여러 정보를 제공합니다. 그러나이를 사용하려면이 정보를 validate 명령에 전달하기 위해 약간의 부두를해야합니다.
참고 : 유효성 검사 명령이 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()
register
메서드 를 호출 할 때 내부에서 발생하는 작업에 대한 자세한 내용 은 입력 유효성 검사 tkinter를 참조하세요.
답변
Bryan의 코드를 연구하고 실험 한 후 최소한의 입력 유효성 검사 버전을 생성했습니다. 다음 코드는 입력 상자를 표시하고 숫자 만 허용합니다.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
아마도 나는 아직 파이썬을 배우고 있으며 모든 의견 / 제안을 기꺼이 받아 들일 것이라고 덧붙여 야 할 것입니다.
답변
Tkinter.StringVar
항목 위젯의 값을 추적 하려면을 사용하십시오 . 에 StringVar
a trace
를 설정하여 의 값을 확인할 수 있습니다 .
다음은 Entry 위젯에서 유효한 수레 만 허용하는 짧은 작업 프로그램입니다.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
답변
Bryan Oakley의 답변을 연구하는 동안 훨씬 더 일반적인 솔루션을 개발할 수 있다는 내용이 나에게 알려졌습니다. 다음 예제에서는 유효성 검사를위한 모드 열거, 유형 사전 및 설정 함수를 소개합니다. 사용 예와 단순성에 대한 데모는 48 행을 참조하십시오.
#! /usr/bin/env python3
# /programming/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}\ni = {!r}\nP = {!r}\ns = {!r}\n'
'S = {!r}\nv = {!r}\nV = {!r}\nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
답변
Bryan의 대답은 맞지만 아무도 tkinter 위젯의 ‘invalidcommand’속성을 언급하지 않았습니다.
좋은 설명은 다음과 같습니다.
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
링크가 끊어진 경우 텍스트 복사 / 붙여 넣기
Entry 위젯은 validatecommand가 False를 반환 할 때마다 호출되는 콜백 함수를 지정하는 invalidcommand 옵션도 지원합니다. 이 명령은 위젯의 관련 텍스트 변수에서 .set () 메서드를 사용하여 위젯의 텍스트를 수정할 수 있습니다. 이 옵션을 설정하는 것은 validate 명령을 설정하는 것과 동일하게 작동합니다. Python 함수를 래핑하려면 .register () 메서드를 사용해야합니다. 이 메서드는 래핑 된 함수의 이름을 문자열로 반환합니다. 그런 다음 해당 문자열 또는 대체 코드를 포함하는 튜플의 첫 번째 요소로 invalidcommand 옵션의 값으로 전달합니다.
참고 : 방법을 알아낼 수없는 한 가지만 있습니다. 항목에 유효성 검사를 추가하고 사용자가 텍스트의 일부를 선택하고 새 값을 입력하면 원래 값을 캡처하고 재설정 할 방법이 없습니다. 항목. 여기에 예가 있습니다.
- 항목은 ‘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을 복구 할 방법이 없습니다. .
답변
다음은 사용자가 숫자 만 입력 할 수있는 입력 값을 확인하는 간단한 방법입니다.
import tkinter # imports Tkinter module
root = tkinter.Tk() # creates a root window to place an entry with validation there
def only_numeric_input(P):
# checks if entry's value is an integer or empty and returns an appropriate boolean
if P.isdigit() or P == "": # if a digit was entered or nothing was entered
return True
return False
my_entry = tkinter.Entry(root) # creates an entry
my_entry.grid(row=0, column=0) # shows it in the root window using grid geometry manager
callback = root.register(only_numeric_input) # registers a Tcl to Python callback
my_entry.configure(validate="key", validatecommand=(callback, "%P")) # enables validation
root.mainloop() # enters to Tkinter main event loop
추신 :이 예제는 calc와 같은 앱을 만드는 데 매우 유용 할 수 있습니다.
답변
import tkinter
tk=tkinter.Tk()
def only_numeric_input(e):
#this is allowing all numeric input
if e.isdigit():
return True
#this will allow backspace to work
elif e=="":
return True
else:
return False
#this will make the entry widget on root window
e1=tkinter.Entry(tk)
#arranging entry widget on screen
e1.grid(row=0,column=0)
c=tk.register(only_numeric_input)
e1.configure(validate="key",validatecommand=(c,'%P'))
tk.mainloop()
#very usefull for making app like calci