problem with tkinter

Eric Brunel eric_brunel at despammed.com
Wed Mar 30 03:26:32 EST 2005


On Tue, 29 Mar 2005 22:32:59 +0200, Pierre Quentel <quentel.pierre at wanadoo.fr> wrote:

> Instead of indexing self.lab by strings, you can index them by the
> attributes themselves : self.lab[self.i], and change line 23 into
>
>       for var in (self.s, self,i)

I really think this is asking for trouble: I suppose that the i and s attributes are meant to change at some point in the future, and you're mapping their *values* to the corresponding labels. So if the value changes, you won't be able to get the label again.

> For your example, I wouldn't have used the "text" option in the
> definition of the labels, then "textvariable" in the callback method
> (procedi) ; I would have used only "text" and no IntVar or StringVar,
> just an integer and a string :

I would have done exactly the contrary, as it is far more easier to use. Using the textvariable option in Label's does not require you to remember the labels, but only the variables used to hold their contents. I'd also use two mappings: the first mapping a name to a Tkinter variable for the label variables, and the second for the values to give to these variables later.

Here is my version of the class code:

class MiaApp:
      def __init__(self, genitore):
         self.mioGenitore = genitore
         ## Mapping for variables
         self.variables = {
           "i" : StringVar(),
           "s" : StringVar()
         }
         ## Mapping for future variable values
         self.values = {
           "i" : 42,
           "s" : "Baobab"
         }
         ## Now, create the labels
         for var in self.variables.values():
           ## Default text
           var.set("[vuota]")
           ## Create label
           lb = Label(self.mioGenitore, width=30, relief=RIDGE, textvariable=var)
           lb.pack()
         ## The button is no more remembered in an attribute, as it does not seem to be needed
         but = Button(self.mioGenitore, text = "Vai!", command = self.procedi)
         but.pack()

      def procedi(self):
        ## Just change the variable values
        for varName in self.variables.keys():
          self.variables[varName].set(self.values[varName])

Note that I only used StringVar's: since the variable holds the *text* for a Label, it is not a good idea to use anything else. I tend to use IntVar, BooleanVar or DoubleVar only when I'm sure it won't ever be set to anything else than an integer, a boolean or a float respectively. So for Label and Entry text variables, I always use a StringVar. In spite of their name, these variable can actually hold anything; you will just get the value you've given to them as text rather than as their original type:

>>> v = StringVar()
>>> v.set(42)
>>> v.get()
'42'

So if you want to get the integer back, you'll need to convert the value explicitely. This is in fact what is done by Tkinter when using an IntVar, but by doing it yourself, you'll be able to decide what to do if the conversion fails instead of just getting a generic TclError.

HTH
-- 
python -c 'print "".join([chr(154 - ord(c)) for c in "U(17zX(%,5.z^5(17l8(%,5.Z*(93-965$l7+-"])'



More information about the Python-list mailing list