entry widget won't validate

M

Mike

I'm trying to arrange for an Entry widget to check whether its data
is all digits and whether the number represented is small enough.
The validate function seem to be called once at startup and not
afterwards:

import sys, Tkinter, tkFileDialog, tkMessageBox

tk=Tkinter
tkfd=tkFileDialog

....
class Functor :
def __init__(self, func, data) :
self.func=func
self.data=data
def __call__(self) : return self.func(self.data)

....
class Levels(tk.Frame) :
def __init__(self, parent) :
tk.Frame.__init__(self, parent)
self.tv=[]
for rgb in range(3) :
self.tv.append(tk.StringVar())
e=tk.Entry(self, textvariable=self.tv[rgb], width=5,
validate='all',
validatecommand=Functor(self.vc, self.tv
[rgb]) )
self.tv[rgb].set(str(levels_av_max))
e.grid(row=2, column=rgb)
lab=tk.Label(self, text='RGB'[rgb])
lab.grid(row=1, column=rgb)
doit=tk.Button(self, text='set levels', command=self.pushed)
doit.grid(row=0, column=0, columnspan=3)

def vc(self, arg2=None) :
print 'vc:', arg2.get()

The print statement run 3 times at startup.
Editing an Entry does not cause any printing.
Any ideas?
 
P

Peter Otten

Mike said:
I'm trying to arrange for an Entry widget to check whether its data
is all digits and whether the number represented is small enough.
The validate function seem to be called once at startup and not
afterwards:

import sys, Tkinter, tkFileDialog, tkMessageBox

tk=Tkinter
tkfd=tkFileDialog

...
class Functor :
def __init__(self, func, data) :
self.func=func
self.data=data
def __call__(self) : return self.func(self.data)

...
class Levels(tk.Frame) :
def __init__(self, parent) :
tk.Frame.__init__(self, parent)
self.tv=[]
for rgb in range(3) :
self.tv.append(tk.StringVar())
e=tk.Entry(self, textvariable=self.tv[rgb], width=5,
validate='all',
validatecommand=Functor(self.vc, self.tv
[rgb]) )
self.tv[rgb].set(str(levels_av_max))
e.grid(row=2, column=rgb)
lab=tk.Label(self, text='RGB'[rgb])
lab.grid(row=1, column=rgb)
doit=tk.Button(self, text='set levels', command=self.pushed)
doit.grid(row=0, column=0, columnspan=3)

def vc(self, arg2=None) :
print 'vc:', arg2.get()

The print statement run 3 times at startup.
Editing an Entry does not cause any printing.
Any ideas?

Quoting http://www.tcl.tk/man/tcl8.5/TkCmd/entry.htm#M12:

"""
In general, the textVariable and validateCommand can be dangerous to mix.
Any problems have been overcome so that using the validateCommand will not
interfere with the traditional behavior of the entry widget. Using the
textVariable for read-only purposes will never cause problems. The danger
comes when you try set the textVariable to something that the
validateCommand would not accept, which causes validate to become none (the
invalidCommand will not be triggered). The same happens when an error occurs
evaluating the validateCommand.
"""

You can verify that this is indeed your problem by changing the Levels.vc()
method to always return True for the moment.

Peter
 
M

Mike

Quotinghttp://www.tcl.tk/man/tcl8.5/TkCmd/entry.htm#M12:

"""
In general, the textVariable and validateCommand can be dangerous to mix.
Any problems have been overcome so that using the validateCommand will not
interfere with the traditional behavior of the entry widget. Using the
textVariable for read-only purposes will never cause problems. The danger
comes when you try set the textVariable to something that the
validateCommand would not accept, which causes validate to become none (the
invalidCommand will not be triggered). The same happens when an error occurs
evaluating the validateCommand.
"""

You can verify that this is indeed your problem by changing the Levels.vc()
method to always return True for the moment.

Returning True does seems to cause vc to be called more often.
I'm still not getting the data I want though.
The variable always gives me the pre-change string.
I gather I need to do something with "%P".
google gave me hints that I should use something called "register",
but I'm not at all clear on what I should do with them.
I don't know how to translate from Tcl to python.
 
P

Peter Otten

Mike said:
Returning True does seems to cause vc to be called more often.
I'm still not getting the data I want though.
The variable always gives me the pre-change string.
I gather I need to do something with "%P".
google gave me hints that I should use something called "register",
but I'm not at all clear on what I should do with them.
I don't know how to translate from Tcl to python.

I don't know Tcl either; the following is the first thing that seemed to
work, after some trial and error:

import Tkinter as tk

def validate(before, after):
print before, "-->", after
return after.isdigit()

if __name__ == "__main__":
root = tk.Tk()
name = root.register(validate)
cmd = 'expr {[%(name)s %(parms)s]}' % dict(name=name, parms="%s %P")
var = tk.StringVar()
entry = tk.Entry(root, textvariable=var,
validate="all", validatecommand=cmd)
entry.pack()
entry.focus_set()
root.mainloop()

Peter
 
M

Mike

I don't know Tcl either; the following is the first thing that seemed to
work, after some trial and error:

import Tkinter as tk

def validate(before, after):
    print before, "-->", after
    return after.isdigit()

if __name__ == "__main__":
    root = tk.Tk()
    name = root.register(validate)
    cmd = 'expr {[%(name)s %(parms)s]}' % dict(name=name, parms="%s %P")
    var = tk.StringVar()
    entry = tk.Entry(root, textvariable=var,
                     validate="all", validatecommand=cmd)
    entry.pack()
    entry.focus_set()
    root.mainloop()

Thanks.
It worked.
I discovered that None is not an acceptable substitute for False.
If validate returns None, it quits being called.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,738
Latest member
JinaMacvit

Latest Threads

Top