简体   繁体   中英

Tkinter “entry” object not updating textvariable variable (Python 3.4)

I am trying to write a simple Python program that will allow a user to input an IP address in decimal, or dotted-decimal format, then convert it to the opposite format and display it in the same entry box (ie, if they enter a decimal IP address, they can click a button and their input will be replaced with the dotted-decimal equivalent).

The problem I'm having is with pulling the data out of the entry box, then putting the new data back into the entry box. I've written an example with just the GUI code, and none of my other conversion logic, to simplify the problem:

import tkinter as tk

root = tk.Tk()
root.title("Test")

win1 = tk.Frame(root)
win1.grid()

x = tk.StringVar()
y = tk.StringVar()

xBox = tk.Entry(win1)
xBox.grid(row = 0, column = 0)
xBox.textvariable = x

yBox = tk.Entry(win1)
yBox.grid(row = 1, column = 0)
yBox.textvariable = y

button = tk.Button(win1,text = "Calculate", command = lambda: copyVal())
button.grid(row = 2, column = 0)

def copyVal():
    print("x: " + x.get())
    print("y: " + y.get())
    xVal = x.get()
    print("xval: " + xVal)
    y.set(xVal)
    root.update_idletasks()

root.mainloop()

Here's what I expect to happen with this code:

  1. The value entered in the top box should be stored in StringVar x .
  2. Clicking the "Calculate" button should run the copyVal() function:
  3. copyVal() gets the value of StringVar x and stores it as xVal .
  4. copyVal() sets the value of StringVar y to match xVal .
  5. The text in the bottom box should now match the text in the top box.

Instead, it does not retrieve the value of StringVar x , so there's nothing to set StringVar y to.

I've tried the following variations:

  1. Using xVal = xBox.get() instead of xVal = x.get() : this retrieves the contents of the top entry box, and sets the value of StringVar y to match it, but the bottom entry box does not change.
  2. Using command = copyVal() instead of command = lambda: copyVal() : the copyVal function executes immediately upon program execution, rather than when the button is pressed.
  3. Moving the copyVal function outside the root mainloop: raises a NameError exception when the button is pressed ( copyVal is seen as not defined).
  4. Moving root.update_idletasks() outside the copyVal function has no effect.

I've looked around for solutions to this issue, but no matter how many people I find who are experiencing similar problems, none of their fixes seem to resolve the issue for me (I usually see them told to use StringVar() to get/set values). I am completely new to working with Tkinter, so I'm sure this is something really basic that I'm overlooking, and I appreciate any advice anyone can offer.

Python objects often allow you to add attributes to them arbitrarily:

>>> class Foo:
...     pass
...
>>> foo = Foo()
>>> foo.a = 1  # No error.  It makes a new attribute.
>>> foo.a
1
>>>
>>> def foo():
...     pass
...
>>> foo.a = 1  # Works with function objects too.
>>> foo.a
1
>>>

So, when you do:

xBox.textvariable = x
...
yBox.textvariable = y

you are not actually setting the Entry s' textvariable options to x and y . Instead, you are creating new attributes named textvariable on each of those objects.

To fix the problem, either set each Entry 's textvariable option when you create the widgets:

xBox = tk.Entry(win1, textvariable=x)
...
yBox = tk.Entry(win1, textvariable=y)

or use the .config method to change them later:

xBox.config(textvariable=x)
...
yBox.config(textvariable=y)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM