Reputation: 156
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:
StringVar x
.copyVal()
function:copyVal()
gets the value of StringVar x
and stores it as xVal
.copyVal()
sets the value of StringVar y
to match xVal
.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:
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.command = copyVal()
instead of command = lambda: copyVal()
: the copyVal
function executes immediately upon program execution, rather than when the button is pressed.copyVal
function outside the root mainloop: raises a NameError
exception when the button is pressed (copyVal
is seen as not defined).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.
Upvotes: 2
Views: 4149
Reputation:
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)
Upvotes: 5