views:

342

answers:

2

Hi everyone,

I'm trying to associate a variable with a Tkinter entry widget, in a way that:

  1. Whenever I change the value (the "content") of the entry, mainly by typing something into it, the variable automatically gets assigned the value of what I've typed. Without me having to push a button "Update value " or something like that first.
  2. Whenever the variable gets changed (by some other part of the programm), I want the entry value displayed to be adjusted automatically. I believe that this could work via the textvariable.

I read the example on http://effbot.org/tkinterbook/entry.htm, but it is not exactly helping me for what I have in mind. I have a feeling that there is a way of ensuring the first condition with using entry's "validate". Any ideas?

Thank you for your input!
Sano

A: 

You want to bind a function to keypress event for the field as explained here, namely the <Key> event.

bpowah
binding to keypress isn't the right solution. It won't, for example, handle the case where you paste with the mouse. Also, binding to a keypress will under default circumstances fire *before* the widget is updated since the update happens in the class bindings which fire after the widget-specific bindings. Textvariables and traces are the way to go.
Bryan Oakley
I think you are correct good sir, Bryan Oakley.
bpowah
+5  A: 

I think you want something like this, in the example below I create a variable myvar and assign it to be textvariable of both a label and entry widget, that way both are coupled and change in entry widget will reflect automatically in label

You can also set trace(http://effbot.org/tkinterbook/variable.htm) on variables, e.g. to write to stdout

from Tkinter import *
root = Tk()
root.title("MyApp")

myvar = StringVar()
def mywarWritten(*args):
    print "mywarWritten",myvar.get()

myvar.trace("w", mywarWritten)

label = Label(root, textvariable=myvar)
label.grid(sticky=W)
label.pack()

text_entry = Entry(root, textvariable=myvar)
text_entry.grid(column=0,row=1, sticky=W)
text_entry.pack()

root.mainloop()
Anurag Uniyal
Thank you, this goes in the right direction, but to work with the variables, I need to convert them to normal python variables. Your example works because the widgets share the same textvariable. But what would you do, for example, if you wanted to print the content of your entry to the standard output whenever it gets changed instead of writing it in a tkinter label?
Sano98
You do this: `text_entry.bind('<Key>', handler)` where `handler` is a function that assigns your python variable. See my answer.
bpowah
@Sano98, i have edited answer, you can easily trace variables for read/write
Anurag Uniyal
@Anurag: Thanks, I used your proposal after I encountered the problems described by Brian Oakley when trying it with binding to keyppress as bpowah suggested. After a little study, I now see that tracing seems taylormade for a problem like this. But when using IntVar instead of StringVar, a ValueError occurs when deleting completely the content of the entry - the empty literal "" is not valid for int conversion. It is given the value 0, which is what I expected, but is there a way to avoid the error? Or to catch it somehow?
Sano98
@Sano98, you may either change the global getint defined in tkinter or may better derive a class from IntVar to overide get, or may be there are better ways, you may ask another question
Anurag Uniyal