Question

I am currently learning the tkinter basics and I'm building a small, super-simple program to test my knowledge on some of the most basic widgets.

I am having a problem with validation and an entry, possibly because of my lack of understanding in the matter... This poses three questions:

1 - How to do what was done here: https://stackoverflow.com/a/4140988/2828287 without the class part. Just doing it when the script runs.

2 - What are all those self. and .self doing there? Which ones are there because that is a class, and which ones are there because of the validating method itself??

3 - What's wrong in my code? based in this explanation >> http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html

from tkinter import *
from tkinter import ttk

# function that should take the '%d' replacer and only validate if the user didn't delete
def isOkay(self, why):
    if why == 0:
        return False
    else:
        return True

okay = entry.register(isOkay) # didn't understand why I had to do this, but did it anyway...
entry = ttk.Entry(mainframe, validate="key", validatecommand=(okay, '%d'))
# the mainframe above is a ttk.Frame that contains all the widgets, and is the only child of the usual root [ = Tk()]
entry.grid(column=1,row=10) # already have lots of stuff on upper rows

The error I'm getting goes like this: "NameError: name 'entry' is not defined" I've tried to change the order of things, but there's always one of these errors.. It points to the line where I do the .register() stuff

--EDITED CODE-- This doesn't throw me an error, but still allows me to delete...

def isOkay(why):
    if (why == 0):
        return False
    else:
        return True

okay = (**root**.register(isOkay), "%d")
entry = ttk.Entry(mainframe, validate="key", validatecommand=okay)
entry.grid(column=1,row=10)

(where the 'root' part is written between ** **, does it have to be the root? Or it can be any parent of the widget that is going to use that? Or it has to be the immediate parent of it? for instance, I have: root >> mainframe >> entry. Does it have to be root, mainframe, or could be both?)

Was it helpful?

Solution

All usages of self are due to the use of classes. They have absolutely nothing to do with the validation. Nothing at all.

Here's an example without using classes, and without the long comment describing the validation function:

import Tkinter as tk

def OnValidate(d, i, P, s, S, v, V, W):
    print "OnValidate:"
    print "d='%s'" % d
    print "i='%s'" % i
    print "P='%s'" % P
    print "s='%s'" % s
    print "S='%s'" % S
    print "v='%s'" % v
    print "V='%s'" % V
    print "W='%s'" % W
    # only allow if the string is lowercase
    return (S.lower() == S)

root = tk.Tk()

vcmd = (root.register(OnValidate), 
        '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
entry = tk.Entry(root, validate="key", 
                      validatecommand=vcmd)
entry.pack()
root.mainloop()

Note: the point of registering a command is to create a bridge between the underlying tcl/tk engine and the python library. In essence it creates a tcl command that calls the OnValidate function, giving it the supplied arguments. This is necessary because tkinter failed to provide a suitable interface to the input validation features of tk. You don't need to do this step if you don't want all of the fancy variables (%d, %i, etc).

The error NameError: name 'entry' is not defined is because you are using entry before you define what entry is. One of the benefits of using classes is that it allows you define methods further down in the file than where you use them. By using a procedural style you are forced to define functions before they are used*.

* technically speaking, you always have to define functions before they are used. In the case of using classes, you don't actually use the methods of a class until after you've created the instance of the class. The instance isn't actually created until very near the end of the file, which lets you define the code well before you use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top