lemi57ssss
lemi57ssss

Reputation: 1380

StringVar on tkinter Entry works. StringVar on ttk.Entry fails

The following code packs two tkinter Entry fields into the root tk window. The displayed text is set via a StringVar. The functions that create the two fields are identical except that one creates a tkinter.Entry object and the other creates a tkinter.ttk.Entry object.

According to Shipman's text both the tkinter.Entry and tkinter.ttk.Entry have textvariable options. They both refer to the same .get() and .set() method for the StringVar. I have been unable to find anything which suggests that the ttk.Entry class requires separate treatment.

Why does ttk.Entry fail to show the text?

enter image description here

(Python 3.5.1 on MS Windows 7)

import tkinter
import tkinter.ttk


def label_2(root):
    label = tkinter.ttk.Entry(root)
    var_text = tkinter.StringVar(name='StringVar 2')
    label.config(textvariable=var_text)
    var_text.set('variable label 2')
    root.update_idletasks()  # Shipman recommended precaution has no effect here
    print(var_text, var_text.get(), label.get())
    label.pack()


def label_3(root):
    label = tkinter.Entry(root)
    var_text = tkinter.StringVar(name='StringVar 3')
    label.config(textvariable=var_text)
    var_text.set('variable label 3')
    root.update_idletasks()  # Shipman recommended precaution has no effect here
    print(var_text, var_text.get(), label.get())
    label.pack()


if __name__ == '__main__':
    root = tkinter.Tk()
    label_2(root)
    label_3(root)
    root.mainloop()

Upvotes: 2

Views: 2513

Answers (2)

Luis Munoz
Luis Munoz

Reputation: 146

I use var_text.trace_add('write', lambda val, index, value: var_text.get()) to keep the reference. Between clases works for me.

Upvotes: 0

Bryan Oakley
Bryan Oakley

Reputation: 386020

Due to differences in implementation, the ttk version of the widget is susceptible to having the variable be garbage-collected. If you keep a persistent reference to the variable your code will work. For example, if you add global var_text inside label_2, it will work.

Personally I see no value in using a StringVar with Entry widgets, unless you are relying on some of the special features of the class such as variable traces, or connecting more than one widget to the same variable.

Note: calling update_idletasks in these functions is completely pointless. This is doubly true since you're calling it before calling pack. That is, until you call pack or grid or place, no task will be added to the idle queue for this particular widget. update_idletask will only affect widgets that have been added to the screen but not drawn yet.

And while you think it has no side effect, it actually does. Calling update_idletasks refreshes all idle tasks, not just the ones created in this function. That being said, it's harmless because all it does is cause a screen refresh, which will happen anyway as soon as mainloop is called.

Upvotes: 3

Related Questions