Tkinter, Entry widget, is detecting input text possible?

13,021

Solution 1

Yes. There are a few different ways to do this, in fact.

You can create a StringVar, attach it to the Entry, and trace it for changes; you can bind all of the relevant events; or you can add a validation command that fires at any of several different points in the sequence. They all do slightly different things.

When a user types 4, there's a key event with just the 4 in it (which doesn't let you distinguish whether the user was adding 4 to the end, or in the middle, or replacing a whole selected word, or…), and then a modification event is fired with the old text,* and then the "key" or "all" validation function is called with the (proposed) new text, and the variable is updated with the (accepted) new text (unless the validation function returned false, in which case the invalidcommand is called instead).


I don't know which one of those you want, so let's show all of them, and you can play around with them and pick the one you want.

import Tkinter as tk

root = tk.Tk()

def validate(newtext):
    print('validate: {}'.format(newtext))
    return True
vcmd = root.register(validate)

def key(event):
    print('key: {}'.format(event.char))

def var(*args):
    print('var: {} (args {})'.format(svar.get(), args))
svar = tk.StringVar()
svar.trace('w', var)

entry = tk.Entry(root,
                 textvariable=svar, 
                 validate="key", validatecommand=(vcmd, '%P'))
entry.bind('<Key>', key)
entry.pack()
root.mainloop()

The syntax for variable trace callbacks is a bit complicated, and not that well documented in Tkinter; if you want to know what the first two arguments mean, you need to read the Tcl/Tk docs, and understand how Tkinter maps your particular StringVar to the Tcl name 'PY_VAR0'… Really, it's a lot easier to just build a separate function for each variable and mode you want to trace, and ignore the args.

The syntax for validation functions is even more complicated, and a lot more flexible than I've shown. For example, you can get the inserted text (which can be more than one character, in case of a paste operation), its position, and all kinds of other things… but none of this is described anywhere in the Tkinter docs, so you will need to go the Tcl/Tk docs. The most common thing you want is the proposed new text as the argument, and for that, use (vcmd, '%P').


Anyway, you should definitely play with doing a variety of different things and see what each mechanism gives you. Move the cursor around or select part of the string before typing, paste with the keyboard and with the mouse, drag and drop the selection, hit a variety of special keys, etc.


* I'm going to ignore this step, because it's different in different versions of Tk, and not very useful anyway. In cases where you really need a modified event, it's probably better to use a Text widget and bind <<Modified>>.

Solution 2

If you just need to do simple things without using trace module you can try

    def objchangetext(self, textwidget):
        print(textwidget.get())  #print text out to terminal

    text1 = tk.Entry(tk.Tk()) 
    text1.bind("<KeyRelease>", lambda event, arg=(0): objchangetext(text1)) 
Share:
13,021
Totem
Author by

Totem

Updated on June 11, 2022

Comments

  • Totem
    Totem almost 2 years

    I have an Entry widget on a simple calculator. The user can choose to enter an equation via the keypad. I was wondering if there was a way to detect a character(from the keypad in my case) being typed into the Entry widget. So, focus is on the widget, user presses '4', it comes up on the widget... can I detect this act, for basic purposes of logging the input?

  • Totem
    Totem over 10 years
    Thanks for in-depth answer. It's going to take me a little while to absorb all of this, as I haven't come across this whole validation business with the Entry widget before, and there's a lot of new information for me here.
  • abarnert
    abarnert over 10 years
    @Totem: Yeah, it's unfortunate that validation commands are what you want 80% of the time, but aren't mentioned anywhere in the tutorial, and aren't described at all in the Tkinter reference docs. So people try to build the same thing by catching <Key> and trying to figure out what the new string will be (or, less often, by tracing the var and then trying to revert an invalid change after the fact).