Inserting a default value into tkinter Entry stops validation

Question:

I have been following the validation for Entry boxes from here. The code below is from the answer with the added condition that if the entered value is 'Q' then the program adds 'test' to the beginning of the Entry value.

However once this value is inserted, all validation appears to go out of the window and the Entry allows upper-case values. Some testing on my program shows the validation command (OnValidate in this case) isn’t being called upon any further events of the Entry (key, focusin/out etc).

import Tkinter as tk
class MyApp():
    def __init__(self):
        self.root = tk.Tk()
        vcmd = (self.root.register(self.OnValidate), 
                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
        self.entry = tk.Entry(self.root, validate="key", 
                              validatecommand=vcmd)
        self.entry.pack()
        self.root.mainloop()

    def OnValidate(self, d, i, P, s, S, v, V, W):
        if S == "Q":
            self.entry.insert(0,"test")
        # only allow if the string is lowercase
        return (S.lower() == S)

app=MyApp()

The reason for me doing this is I want the Entry to display a default value if its value is left empty after any changes that are made by a user. (i.e. my condition would be if not P on focusout)

Any ideas how to implement this or what’s going wrong in the above much appreciated.

Asked By: Jdog

||

Answers:

I’m going to answer completely based on:

I want the Entry to display a default
value if its value is left empty after any changes that are made by a
user.

and hope that this example points you to what you want:

import tkinter

def analyze(event=None):
    content = entry_contents.get()
    if content == "":
        entry_contents.set("default")

root = tkinter.Tk()

entry_contents = tkinter.StringVar()
entry = tkinter.Entry(root, textvariable=entry_contents)
entry.grid()

text = tkinter.Text(root, font=("Georgia", "12"))
text.grid()

entry.bind("<FocusOut>", analyze)

root.mainloop()

or if a control variable wont be of any use to you:

import tkinter

def analyze(event=None):
    content = entry.get()
    if content == "":
        entry.insert(0, "default")

root = tkinter.Tk()

entry = tkinter.Entry(root)
entry.grid()

text = tkinter.Text(root, font=("Arial", "12", "bold"))
text.grid()

entry.bind("<FocusOut>", analyze)

root.mainloop()
Answered By: Honest Abe

The validatecommand option is designed for validation only, not for doing other sorts of things. The behavior you see is the documented behavior.

According to the official tk documentation on entry validation:

… The validate option will also set itself to none when you edit the entry widget from within either the validateCommand or the invalidCommand.

(note: tkinter is little more than a wrapper around the tcl implementation of tk. For this reason, the tcl/tk documentation can be used as the definitive guide to the behavior of Tkinter)

Answered By: Bryan Oakley
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.