Confusing problem between Tkinter.Intvar() and self declared variable class
Peter Otten
__peter__ at web.de
Tue Jan 27 04:48:07 EST 2004
Marc wrote:
> Hi all,
>
> I was using Tkinter.IntVar() to store values from a large list of
> parts that I pulled from a list. This is the code to initialize the
> instances:
>
> def initVariables(self):
> self.e = IntVar()
>
> for part, list in info.masterList.items():
> obj = setattr( self.e, part, IntVar() )
It seems odd to use an IntVar as a container for IntVar instances.
obj will always be set to None; just use setattr().
>
> That allowed me to save bundles of info without having to create
> another large dictionary or list. I was using the variable in entry
A Python object is just a dictionary in disguise.
> boxes to store the amount of parts ordered:
>
> Entry( cscGroup.interior(), width=3, textvariable =
> getattr(self.e, part),
> text=e.get()).grid(row=x, column=2, padx=4
> )
>
> However, I ran into problems when I tried to pickle the instances in
> order to recall them later. To fix that problem I created my own
> simple data class that allowed me to save the data the same way while
> also having the ability to pickle it:
>
> class DataVar:
> def __init__(self):
> self.data = 0
> self.partName = ""
>
> def set(self, value):
> self.data = value
>
> def get(self):
> return self.data
>
> But I just discovered another problem. It doesn't appear to hold data
> the same way. The information appeared global when it was IntVar().
> Now when I go outside the class that set up the entry boxes, the
> information does not appear to be in DataVar. I print out the info the
> following way:
>
> def printValues(self):
> for part, list in info.masterList.items():
> e = getattr(self.e, part)
> print str(part) + " --->" + str( e.get() )
>
> This function is in the same class that initialized the DataVar
> variables and also that called the class that setup the window to
> enter the amount of parts. When I call that class I pass in the
> variable in the following way:
>
> spares = Spares(self.master, self.e)
>
> So obviously there's something about Tkinter that causes the info to
> be global. But even though the DataVar class is an independent class,
> for some reason the information is not being maintained.
>
> Does anyone have any idea why this is happening and how to fix it?
I wasn't able to completely follow the last part of your post, so below is a
working version of what I /think/ you are trying to do. The important part
is a pickle-enhanced container for IntVars that stores their values instead
of the instances. It could easily be enhanced to support, say, StringVar by
inspecting the type of the values in the __setstate__() method.
<crocodile.py>
import Tkinter as tk
import pickle
class Namespace:
pass
class IntVars:
""" Every attribute is suposed to be a TKinter.IntVar instance """
def __getstate__(self):
d = dict(self.__dict__)
for k in d:
d[k] = d[k].get()
return d
def __setstate__(self, d):
for k, v in d.iteritems():
iv = tk.IntVar()
iv.set(v)
setattr(self, k, iv)
info = Namespace()
info.masterDict = {
"bird": 1,
"elephant": 2,
"crocodile": 3,
}
FILENAME = "crocodile.pickle"
class LoadError(Exception): pass
class Main(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
try:
self.loadVariables()
except LoadError:
self.initVariables()
self.saveVariables()
self.initControls()
def loadVariables(self):
try:
f = file(FILENAME)
except IOError:
raise LoadError
else:
# error handling is *incomplete*
try:
self.e = pickle.load(f)
finally:
f.close()
def saveVariables(self):
f = file(FILENAME, "wb")
try:
pickle.dump(self.e, f)
finally:
f.close()
def initVariables(self):
self.e = IntVars()
for part, lst in info.masterDict.iteritems():
iv = tk.IntVar()
iv.set(lst)
setattr(self.e, part, iv)
def initControls(self):
interior = self # cscGroup.interior()
x = 0
for part, lst in info.masterDict.iteritems():
e = tk.Entry(interior, width=3,
textvariable=getattr(self.e, part)) # text=... has no effect
e.grid(row=x, column=2, padx=4)
x += 1
self.button = tk.Button(self, text="Save values",
command=self.saveVariables)
self.button.grid(row=x, column=2, padx=4)
m = Main()
m.mainloop()
</crocodile.py>
Peter
More information about the Python-list
mailing list