tkinter questions: behavior of StringVar, etc

A

Alan G Isaac

I'm a complete newbie to GUI.
I have a couple questions about tkinter.

1. Where is the list of changes
in Python 3's tkinter?

2. What exactly is the role of the root object,
traditionally created as ``root=tk.Tk()``?
What is an example where one should create this
before creating a Frame instance (which will
otherwise implicitly create one as its master)?

2. Suppose I ``import tkinter as tk`` and
then try ``s1=tk.StringVar()``. This fails
because no "master" is set. Why does a
Variable need a master?

3. Now suppose I set ``root = tk.TK()`` and
then try ``s1=tk.StringVar()``. This
works fine but now seems a bit magical:
how has the value of the "master" been
set?

4. Another bit of magic:
Suppose I ``import tkinter as tk`` and
then try ``f1=tk.Frame()``. This works
fine: apparently calling Frame also
leads to implicit creation of a "master".
Why is what is good for the gander (i.e.,
implicit master creation for a Frame) not
good for the goose (i.e., a Variable)?
(Here I assume that there has been an
answer to 2. above.)

5. Reading around a bit,
it seems common to recommend setting
the values of Variables rather than initializing
them. Why? I cannot see the reason to avoid
``s1=tk.StringVar(value="this works fine")``
and it looks like ``tk.StringVar(()`` is in any
case initialized (to an empty string).

6. Why is str(s1) not its value? More generally,
why does a StringVar not behave more like a string?

Thanks for any insights,
Alan Isaac
 
M

Mike Driscoll

I'm a complete newbie to GUI.
I have a couple questions about tkinter.

1. Where is the list of changes
    in Python 3's tkinter?

2. What exactly is the role of the root object,
    traditionally created as ``root=tk.Tk()``?
    What is an example where one should create this
    before creating a Frame instance (which will
    otherwise implicitly create one as its master)?

2. Suppose I ``import tkinter as tk`` and
    then try ``s1=tk.StringVar()``.  This fails
    because no "master" is set. Why does a
    Variable need a master?

3. Now suppose I set ``root = tk.TK()`` and
    then try ``s1=tk.StringVar()``.  This
    works fine but now seems a bit magical:
    how has the value of the "master" been
    set?

4. Another bit of magic:
    Suppose I ``import tkinter as tk`` and
    then try ``f1=tk.Frame()``.  This works
    fine: apparently calling Frame also
    leads to implicit creation of a "master".
    Why is what is good for the gander (i.e.,
    implicit master creation for a Frame) not
    good for the goose (i.e., a Variable)?
    (Here I assume that there has been an
    answer to 2. above.)

5. Reading around a bit,
    it seems common to recommend setting
    the values of Variables rather than initializing
    them.  Why?  I cannot see the reason to avoid
    ``s1=tk.StringVar(value="this works fine")``
    and it looks like ``tk.StringVar(()`` is in any
    case initialized (to an empty string).

6. Why is str(s1) not its value?  More generally,
    why does a StringVar not behave more like a string?

Thanks for any insights,
Alan Isaac

Try Google and the Python website. There is tons of info on the Python
wiki:

http://wiki.python.org/moin/TkInter

There are also some books that walk you through Tkinter application
creation, for example,Lutz's "Programming Python".

- Mike
 
A

Alan G Isaac

I'm a complete newbie to GUI.
I have a couple questions about tkinter.
1. Where is the list of changes
in Python 3's tkinter?
2. What exactly is the role of the root object,
traditionally created as ``root=tk.Tk()``?
What is an example where one should create this
before creating a Frame instance (which will
otherwise implicitly create one as its master)?
2'. Suppose I ``import tkinter as tk`` and
then try ``s1=tk.StringVar()``. This fails
because no "master" is set. Why does a
Variable need a master?
3. Now suppose I set ``root = tk.TK()`` and
then try ``s1=tk.StringVar()``. This
works fine but now seems a bit magical:
how has the value of the "master" been
set?
4. Another bit of magic:
Suppose I ``import tkinter as tk`` and
then try ``f1=tk.Frame()``. This works
fine: apparently calling Frame also
leads to implicit creation of a "master".
Why is what is good for the gander (i.e.,
implicit master creation for a Frame) not
good for the goose (i.e., a Variable)?
(Here I assume that there has been an
answer to 2. above.)
5. Reading around a bit,
it seems common to recommend setting
the values of Variables rather than initializing
them. Why? I cannot see the reason to avoid
``s1=tk.StringVar(value="this works fine")``
and it looks like ``tk.StringVar(()`` is in any
case initialized (to an empty string).
6. Why is str(s1) not its value? More generally,
why does a StringVar not behave more like a string?



Try Google and the Python website. There is tons of info on the Python
wiki:
http://wiki.python.org/moin/TkInter
There are also some books that walk you through Tkinter application
creation, for example,Lutz's "Programming Python". [/QUOTE]


Sorry, but I do not see the answers to any of the above
questions, not even the first one. Do you? (One might
believe question 2 is answered, but if you read it, I
think you will see why I do not.)

Cheers,
Alan Isaac
 
F

Francesco Bochicchio

Alan G Isaac ha scritto:
Sorry, but I do not see the answers to any of the above
questions, not even the first one. Do you? (One might
believe question 2 is answered, but if you read it, I
think you will see why I do not.)

Cheers,
Alan Isaac


I think you need a bit of background (if not, just ignore this post):

1. Tkinter is only a thin wrapper over Tk, a GUI library initially
developed for Tcl language, so many of the answer to the design choices
you question (e.g. what is the master) cannot between answered within
the python documentation but should be searched in the Tcl/Tk
documentation. So google for tcl/tk.
Anyway, all GUI libraries I know of build the GUI as a hierarchical
structure. The master (often called root) ia the root of this
hierarchy, and you have to build it before building the rest.

2. Another good source of information is the source of Tkinter itself,
which is mostly in the Tkinter.py file. This is available in your python
installation, so dig into it: if you for instance look at the __init__
method of the Variable class (which is the basic class of StringVar),
you will easily find the 'magic' to which you refer to.
If you don't like the choices which have been made there (e.g not
automagically creatinga a master for variables but doing it for frames
), you could try and submit a patch :)

3. Usually the changes between one version of python and the next are
documented (but not in all gory details) in "What is new" documents you
can find in python.org site. I'm not aware of any change for Tkinter,
in Python 3.0 but go read it yourself. If you want more details you
could always fetch the Tkinter.py file (or others) of bot versions and
make a diff.

Ciao
 
A

Alan G Isaac

OK, that was plain rude. a couple of questions is not six questions.
A reply telling you how to get to some of what you are looking for
is assistance. If you want exact answers to an array of questions,
pay someone to fetch you the answers, or do your own homework.

Clearly I am too grumpy this weekend.


Yes you are too grumpy. It is *not* rude to point
out that the answers are not where I was pointed.
The available docs are much more focused on "how"
rather than on "why".

Please show me how to use that response to get
even one of the answers. (Please skip #2, since I
fear a repetition of the kind of answer in all the docs,
which is half an answer.) Or, withdraw your claim.

Btw, I cannot find the answers in Grayson's book either.
It's a big book though, and covers much ground, so I
do not deny the answers might well be in there somewhere.

Let's try just these two:
- Why does a Variable need a master?
- If s is a StringVar instance, why is
str(s) its name rather than its value?

Thank you,
Alan Isaac
 
A

Alan G Isaac

1. Tkinter is only a thin wrapper over Tk, a GUI library initially
developed for Tcl language, so many of the answer to the design choices
you question (e.g. what is the master) cannot between answered within
the python documentation but should be searched in the Tcl/Tk
documentation. So google for tcl/tk.
Anyway, all GUI libraries I know of build the GUI as a hierarchical
structure. The master (often called root) ia the root of this
hierarchy, and you have to build it before building the rest.

I understand this. But I do not understand what we get
by having each Variable instance register a master.
(In contrast, e.g., to a container widget, such as a Frame,
where I do not have this question.)

2. Another good source of information is the source of Tkinter itself,
which is mostly in the Tkinter.py file.

In Python 3, I'm finding most of the useful stuff to be in
``tkinter/__init__.py``. It is indeed useful, but not
always transparent. At least to a new user.

if you for instance look at the __init__ method of the
Variable class (which is the basic class of StringVar),
you will easily find the 'magic' to which you refer to.

What we find is that Variable is initialized with:
if not master:
master = _default_root
which in turn is initialized to None. I understand this.
Actually, talking this through, I get it now. I was not
properly thinking about the use of module level globals.
Thanks.

If you don't like the choices which have been made there
(e.g not automagically creatinga a master for variables
but doing it for frames ), you could try and submit
a patch :)

I am not so presumptuous. I just want to understand why a
Variable needs a master. How is this used?

And, I would like to understand if there is a *reason* that
a StringVar instance, for example, does not behave more like
a string.

3. Usually the changes between one version of python and the next are
documented (but not in all gory details) in "What is new" documents you
can find in python.org site. I'm not aware of any change
for Tkinter, in Python 3.0 but go read it yourself.

I did look there, and explicitly got only that the new name
is ``tkinter``. However, there are other changes, e.g. the
names and location of ``colorchooser`` and ``filedialog``.
I realize now that the statement "related modules have been
grouped into packages, and usually the submodule names have
been simplified" is supposed to capture all this, but an
explicit list would have been helpful to me. (And,
I assume, to others.) I also just assumed that some active
user had made a list of changes, which I had overlooked, but
that someone on this list would be aware of.

Thanks,
Alan Isaac
 
J

John Posner

Scott David Daniels said:

I agree with Scott that Alan could use a little attitude adjustment. OTOH,
the following IDLE transcript does suggest that some "magic" is occurring:

Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ss = StringVar()
File "C:\Python26\lib\lib-tk\Tkinter.py", line 251, in __init__
Variable.__init__(self, master, value, name)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 182, in __init__
self._tk = master.tk
AttributeError: 'NoneType' object has no attribute 'tk'

Here's the "magic" in this situation, which is not exactly highlighted in
existing Tkinter documentation:

If you do not specify a master object in the StringVar() statement, the
Tk object becomes
the variable's master. If no Tk object exists, an error occurs.

You can create a Tk object explicitly with the Tk() statement. A Tk
object is created
implicitly when you create a widget -- for example, with Frame() or
Entry().

I *did* find this in the "Configuration Interface" section of
Fredrik Lundh's "An Introduction to Tkinter"
(http://www.pythonware.com/media/data/an-introduction-to-tkinter.pdf):

widgetclass(master, option=value, ...) -> widget

Create an instance of this widget class, as a child to the given
master, and using the given options. All options have default
values, so in the simplest case, you only have to specify the
master. You can even leave that out if you really want; Tkinter
then uses the most recently created root window as master.

BTW, the last sentence appears to be false in Python 2.6.1 -- the *first*
root window is used as the master.





E-mail message checked by Spyware Doctor (6.0.0.386)
Database version: 5.12060
http://www.pctools.com/en/spyware-doctor-antivirus/
 
A

Alan G Isaac

Alan asked:
The answer to that, grasshopper, lies in the answer to the question,
"What are StringVars designed to do?" StringVars, and IntVars, and ...
are elements to receive, hold, and propagate changes to values that
will produce effects in the programs behavior or display. I find
IntVars easier to explain, since you get values for numbers lots of
ways. If a slider updates an IntVar, a signal must reach anything
"interested" in the value of that IntVar. For example, you have a
rectangle, and a display of its height, width, area, and aspect ratio.
If you change the height or the width, the area and aspect ratio need
updating (as well as the value in the height or width).

In short, a Variable can have observers. My question does
not lie here. At least, you have not persuaded me that it does.

Rather than building systems where every control maintain
lists of what to notify and how to communicate the value,
things like IntVars and StringVars work as data store and
signal propagation points. One of the Vars is more Var
than value: a place to go to look for the current value,
and a place to register for notification when changes
happen. Clearly you cannot signal changes from a variable
unless the whole event mechanism is running.


I take this to be the core of your argument: that a Variable
cannot signal to a widget until the event mechanism is up
and running. But of course if you create e.g. a Frame, the
"root" is automagically created. So I do not understand
your reasoning.

To elaborate, where could things go wrong if I could
instantiate a Variable without first instantiating a Tk root
object? You note that the variable would have no work to do
in an event mechanism until that mechanism was created, but
then again, it could not (right?) have an relevant
association under the current architecture until a root was
instantiated.

For example, suppose I want to associate an ``Entry`` with
a ``StringVar``. If I have not already created a root,
I would have to create the ``Entry`` first (which
auotmagically creates the root) and then the ``StringVar``,
but what is the payoff from this restriction?

A StringVar needs to know where to send signals about its
changes. Thus two different StringVars containing the
same text can behave quite differently, as each may be
hooked into a different network of event propagation.

Yes of course. See above.
Just to be clear, I am not so presumptuous as to try to
challenge the design. I am trying to understand it.

Here's what I think the answer might be (following a hint
from Francesco). I think that this restriction serves no
direct function in Python, but is used manage communication
between Python and Tk/Tcl. That is, the current design
simply ensures that *at creation* a Variable has a corresponding
Tcl variable and is named in a way that matches the order of
creation. (Roughly. In addition it looks like multiple Variable
instances can share a name and thus reference a single Tcl
variable.) While this does not explain why a Variable,
unlike a Widget, will not create a root object on an as
needed basis, it does explain why the root object is
required for Variable creation.

Thanks,
Alan Isaac

PS If you were also offering an answer to the second question,
I missed it altogether, but although it is perhaps slightly
less obvious than with a StringVar, I would ask the same
basic question of an IntVar: why does it not behave more
like an int? E.g., why is ``int(IntVar(value=5))`` an
error, or at least, why is ``str(IntVar(value=5))`` the name
of the IntVar instead of '5'?
 
A

Alan G Isaac

You ask, "What exactly is the role of ...", rather than
saying something like, "I don't understand the role of
...", and continue to ask why the code is not architected
the way you first expected it to be architected, calling
those things you do not understand "magic" (not
"magically" which would at least invoke a sense of wonder,
rather than indignation).


Clearly there are some cultural differences here. I am not
a CS type. I would not presume to criticize the
architecture, and in my world, questions are generally
assumed to be what they appear to be: questions.

Additionally, I confess to be completely ignorant of the
nuances you suggest between using the term "magic" and
saying something happened "magically". I meant it only in
the sense that John has since used it: as suggesting
something not obvious (to me) was taking place. I had no
intent to communicate indignation with this term and indeed
am startled that it could be so construed. Is this nuance
really universal on this list?

Cheers,
Alan Isaac
 
A

Alan G Isaac

In this case, your choice of wording
(the nearest thing we have in print to "tone of voice") did not
inspire me to go digging around in source that you have just as
easy access to, in order to answer questions that I'm not
particularly interested in.


I certainly was not trying to inspire you to do so.
The question was meant for people who had this
level of understanding already, or who already
knew with some specificity where I might dig.

Since you did not address my question about
the nuance of "magic", I'm inclined to treat
you as a "no" vote.

Thanks,
Alan Isaac
 
A

Alan G Isaac

Right. Tkinter could have been built to make a root at
the first instantiation of a StringVar or IntVar, but it
wasn't. Answering your why is a bit like answering the
"Why did Picasso choose primarily blue in his Blue Period,
rather than green?"

But this is a fine answer: a choice had to be made, and
nothing much seemed to be at issue, so this was the simpler
(or whatever) choice. I did not ask for a deeper answer,
but if that is the correct answer, it cannot be expected to
be obvious to those who are new to the code.

Hmmm -- where cvould things go wrong --- segment fault?
what happens when you call code that hasn't had the setup run?

Again, I do not understand, and I think I explained why.
Of course if the Variable is not registered with Tcl/Tk at
*creation*, it will have to be registered when first
associated with a widget (or in any way with the event
mechanism). But of course my question was why a Variable
cannot exist independently of the event mechanism. Since
you did not critique the answer I proposed in my previous
post, I assume you do not have a big problem with it. If it
is correct, it is the kind of answer I was looking for.

What happens to your TV when you change the channel before
turning it on?

I think we can agree this is a safe action, but the result
depends on the kind of TV (and on what "turning it on" means).
So I think your analogy makes my point: allowing
the state of the variable to be registered at use rather than
creation is feasible, although it would perhaps not be best.
(E.g., it would not be simplest.)

Printing a StrVar is not the same as printing the contents
of a StrVar. Having "magic" conversions happen for you
when they can be useful simply allows you to make mistakes
about what things are what.

This sounds like an argument against duck typing, and maybe
even an argument for eliminating most of the special method
names, although I'm sure you did not mean it to be this. ;-)

Thanks for the discussion. Your willingness to converse
with someone whose initial "tone" irritated you has helped
me to improve my understanding, and hopefully some future
user will find this thread of some use.

Cheers,
Alan Isaac
 
A

Alan G Isaac

Since you did not address my question about
the nuance of "magic", I'm inclined to treat
you as a "no" vote.


And you'd be wrong.[/QUOTE]


So seriously, you'd read e.g. John's usage
of the term "magic" (in this thread)
to suggest "indignation"?

Curious. But I recognize that cultures differ.

Alan Isaac
 
A

Alan G Isaac

The object traditionally called root is in fact an instance of the tcl
interpreter that will get the commands generated by the Tkinter module. Due to
tk architecture, creating this interpreter will also create a window, which is
inteneded to be your application's main window. This window is called '.' in
tcl/tk. The root object in Tkinter then represents this '.' window. So the
instance of Tk is actually 2 things:
- The interpreter itself;
- The main window for your application.
OK.

As for when you should create explicitely an instance of Tk, well, I'd say
always ;-) Creating an instance of Frame without creating a Tk instance first
will actually create one, but you'll have no direct access to it.

If I start by creating a frame `f`, then ``f.master`` is the root.
Still, I take your point.
And you
might want an access to it for quite a number of reasons: hiding it, make it
an icon, add menus to it, and so on... All these operations can be done on
actual windows, not on a Frame which is just a container widget.

Useful. Thanks.
All Tkinter widget actually
reference their interpreter in their tk attribute. The StringVar will probably
just use that.

Yes, I see how this works now.
The Tk instance is registered in a hidden variable in the Tkinter module. When
you don't specify a master, it'll use the latest created Tk instance one by
default. BTW, the latest should be the only one: it is quite unsafe to create
several Tk instances in the same application.

I have no desire to do this, but might you pin down "unsafe"?
I guess
that having a window automatically created when you just try to instantiate a
variable has been considered weird. But it's just a guess.

Yes, I am making that same guess.

Thanks!
Alan Isaac
 
A

Alan G Isaac

The string representation of Tkinter objects seems to be a design principle in
this module: it'll always evaluate to the representation this object has at
tcl level. Since a XxxVar is represented by an actual variable at tcl level,
its string representation is the name of this variable. I guess it's quite
easier to build the commands that'll be passed to the tcl interpreter this
way: you don't have to check the type of the objects you handle, but pass them
through str and insert the result directly in the command.


This is a helpful answer: it "feels" right and can be
explored further.

Thanks,
Alan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top