Reputation: 841
I am just learning the TKinter module for Python and have a simple text box that asks for speed and time and prints distance. For some reason my distance is always whatever the speed is initialized as times what ever I input as time. I think I either need a second entry or to globalize my variables but I was wondering what you
from Tkinter import *
master = Tk()
speed = 10; time = 10; d = 50
e = Entry(master)
e.pack()
e. delete(0, END)
e.insert(0, "Enter Speed")
def callspeed():
s = e.get()
speed = int(s)
e.delete(0, END)
e.insert(0, "Enter time")
def calltime():
t = e.get()
time = int(t)
d = speed * time
print d
bs = Button(master, text="Speed", width=15, command=callspeed)
bs.pack()
bt = Button(master, text="Time", width=15, command=calltime)
bt.pack()
mainloop()
Upvotes: 0
Views: 198
Reputation: 365717
The problem is that this line in callspeed
:
speed = int(s)
Creates a new local variable called speed
, instead of updating the global variable.
To fix it, you just need a global
declaration:
def callspeed():
global speed
s = e.get()
speed = int(s)
e.delete(0, END)
e.insert(0, "Enter time")
The exact rules are a bit complicated ("free variables"—which basically means variables you reference but never assign to—can come either from a closure or from globals; variables you assign to are always local), but the safe thing to do is to always add a global
statement when you want to use a global variable.
Or, even safer, don't use global variables in the first place.
For example, you could move all of this code, or just the "model" part of it, into a class, and make speed
an instance variable.
class ThingyModel(object):
def __init__(self, e):
self.speed, self.time, self.d = 10, 10, 50
self.e = e
def callspeed(self):
s = self.e.get()
self.speed = int(s)
self.e.delete(0, END)
self.e.insert(0, "Enter time")
def calltime(self):
t = self.e.get()
self.time = int(t)
self.d = self.speed * self.time
print d
e = Entry(master)
e.pack()
e. delete(0, END)
e.insert(0, "Enter Speed")
model = ThingyModel(e)
bs = Button(master, text="Speed", width=15, command=model.callspeed)
bs.pack()
bt = Button(master, text="Time", width=15, command=model.calltime)
bt.pack()
(This isn't a real MVC design, because the "controller" part is scattered all over, and the "view" isn't organized into any kind of structure, but it should be enough to show the basic idea.)
Upvotes: 1
Reputation:
abarnert is right, global variables are messy. Here's my rewrite with speed and time as local variables:
from Tkinter import *
master = Tk()
Label(master,text="Speed:").grid(row=0,column=0)
Label(master,text="Time:").grid(row=1,column=0)
speed_entry = Entry(master)
speed_entry.grid(row=0,column=1)
time_entry = Entry(master)
time_entry.grid(row=1,column=1)
def submit():
speed = float(speed_entry.get())
time = float(time_entry.get())
print "Speed is",speed
print "Time is", time
print "Distance is",speed*time
Button(master,text="Submit",command=submit).grid()
master.mainloop()
Upvotes: 0