Implicit initialization is EVIL!

R

rantingrick

Tkinter has a major flaw and this flaw has been with us for many many
years. What is the flaw? Well the title says it all folks... IMPLICIT
INITIALIZATION IS EVIL. Still confused, well let me explain.

Unlike most GUI libraries the Tkinter developers thought is would
"just wonderful" if the root GUI window just sprang into existence if
the programmer "somehow" forgot to create one. Does anyone remember
the old adage...

""" The road to hell is paved with good intentions? """

....as you're about to see this road is paved in gold around thee
parts! You're probably thinking to yourself that i am stretching the
truth for the sake of drama? Well i wish i could answer yes, but i
cannot. So without further "a due" let me show you some code...

## START CODE ##
from Tkinter import *
label = Label(parent=None, text='This is an example of poor GUI
design!')
label.pack()
label.mainloop()
## END CODE ##

As you can see the root window is auto created for the caller and this
sort of hand holding only served to confuse the hell of out new folks!
Sure it's "cute" (and all that type of nifty swiftly crap!) but it is
EVIL! A new user should learn from day one the hierarchy of a GUI.

-root window
-optional widgets
--optional sub windows
---optional widgets
---and on and on

root = Tk() # Or a derived class of Tk
frame = Frame(root)
w = Widget(frame)
and on and on and on

We should never propagate this sort of confusion throughout our
community. Please remove this dangerous design pattern immediately.
 
C

Chris Angelico

A new user should learn from day one the hierarchy of a GUI.

-root window
-optional widgets
--optional sub windows
---optional widgets
---and on and on

You're forgetting all the other crucial parts of the hierarchy. A new
user should be forced to declare a Desktop that s/he wants the window
on, and a Screen, and choose which video driver to use too! Implicit
acceptance of defaults is EVIL! Oh, and while you're at it, Python's
habit of letting you skip variable declarations is EVIL too. A new
user should learn from day one that variables need to be stored
somewhere, so Python should stop coddling its newbies and actually get
them to do things right:

var(0x14205359) x # Don't forget to provide an address where the
object will be located
x=42

After all, everyone's gotta learn about segfaults some day!

Chris Angelico
 
R

Roy Smith

Chris Angelico said:
var(0x14205359) x # Don't forget to provide an address where the
object will be located
x=42

After all, everyone's gotta learn about segfaults some day!

0x14205359 is more likely to give a bus error (odd address) than a
segfault :)
 
G

Gregory Ewing

rantingrick said:
Unlike most GUI libraries the Tkinter developers thought is would
"just wonderful" if the root GUI window just sprang into existence if
the programmer "somehow" forgot to create one.

IMO the real problem here is the existence of a privileged
"root" window at all. No GUI platform I know of has any
such concept (except for a "desktop" window that represents
the whole screen, which is not the same thing). All top-level
windows should have equal status.
 
C

Chris Angelico

IMO the real problem here is the existence of a privileged
"root" window at all. No GUI platform I know of has any
such concept (except for a "desktop" window that represents
the whole screen, which is not the same thing). All top-level
windows should have equal status.

I don't know Tkinter, but from the look of the example code, he's
creating a Label that's not attached to a window, and then packing it
into nothing. The toolkit kindly creates him a window. Is that the
"root GUI window" that he means? A basic top-level window?

Chris Angelico
 
R

rantingrick

IMO the real problem here is the existence of a privileged
"root" window at all. No GUI platform I know of has any
such concept (except for a "desktop" window that represents
the whole screen, which is not the same thing). All top-level
windows should have equal status.


I dunno, it's natural to create a parent-child hierarchy when GUI
programming with any library. So i am not completely sure what you are
implying here? When you close the main application widow you would
expect all child windows to close. Or likewise when you iconify the
main window you would expect the other windows to do the same. Sure
you could do this yourself by sending messages to all the other
windows but Tkinter does this for you automatically. And how does
Tkinter know which windows to configure? A parent-child relationship
that's how.
set(['_setup', '_do'])

You say "root" windows are bad however any parent-child relationship
has to BEGIN somewhere. For Tkinter the beginning of this dynasty is
an instance of the Tkinter.Tk[1] window from which all other windows
and widgets are made children. HOWEVER any of the windows ARE in fact
instances of Tk.Toplevel[1]. So they ARE all equal because they all
have the same methods available to them.
'Toplevel widget of Tk which represents mostly the main window\n of
an appliation. It has an associated Tcl interpreter.'
[QUOTE= said:
inspect.getmro(Tkinter.Toplevel)
[/QUOTE]
(<class Tkinter.Toplevel at 0x02742690>, <class Tkinter.BaseWidget at
0x02742630>, <class Tkinter.Misc at 0x02742570>, <class Tkinter.Wm at
0x0272F780>)

But let's dig a little deeper here. Your comment suggests that you
"personally" need to create multiple windows for your applications. Is
this correct? If so i pity any users of such application as they would
be thoroughly confused. Most applications consist of one main window
(a Tkinter.Tk instance). The only need for extra Toplevel windows is
in the form of modal dialogs (use tkSimpleDialog.Dialog) or tool
windows (use Tk.Toplevel with attribute '-toolwindow'=True).

I don't see how your statements carry any weight here. Could you
explain please?

[1] http://effbot.org/tkinterbook/tkinter-application-windows.htm
[2] http://effbot.org/tkinterbook/toplevel.htm
 
R

rantingrick

I don't know Tkinter, but from the look of the example code, he's
creating a Label that's not attached to a window, and then packing it
into nothing. The toolkit kindly creates him a window. Is that the
"root GUI window" that he means? A basic top-level window?

Yes. But to be specific the "root" is an instance of Tkinter.Tk which
is a toplevel that has a TCL interpreter attached.
 
R

Robin Becker

On 03/07/2011 23:21, Chris Angelico wrote:
..........
var(0x14205359) x # Don't forget to provide an address where the
object will be located
x=42
.........
did you forget to specify the memory bank and computer (and presumably planet
etc etc....)
-molly-coddled-ly yrs-
Robin Becker
 
C

Chris Angelico

But let's dig a little deeper here. Your comment suggests that you
"personally" need to create multiple windows for your applications. Is
this correct? If so i pity any users of such application as they would
be thoroughly confused. Most applications consist of one main window
(a Tkinter.Tk instance). The only need for extra Toplevel windows is
in the form of modal dialogs (use tkSimpleDialog.Dialog) or tool
windows (use Tk.Toplevel with attribute '-toolwindow'=True).

Uhh, sorry. No. There are plenty of good reasons for one application
to make multiple top-level windows, and if I ever find myself using a
toolkit that makes this difficult, I'll either be hacking the toolkit
or using a different one. I've been building GUI applications for far
too long to not want features like that.

ChrisA
 
R

rantingrick

oops. should have used symmetric_difference!
set(['_w', '_setup', 'report_callback_exception', '_do',
'__getattr__', 'loadtk', '_loadtk', 'readprofile'])
 
R

rantingrick

Uhh, sorry. No. There are plenty of good reasons for one application
to make multiple top-level windows, and if I ever find myself using a
toolkit that makes this difficult, I'll either be hacking the toolkit
or using a different one. I've been building GUI applications for far
too long to not want features like that.

And those reasons are...?
 
C

Chris Angelico

And those reasons are...?

As varied as the applications that call on them. One example that
springs to mind: Our database front end has "table view" and "record
view", where you get one table view and from that you can view as many
records as you like. Users may choose to effectively switch from one
view to the other, or they may open up two or more record views and
have them and the table view all on screen simultaneously. This is not
a modal dialog; it's not even a modeless dialog - it's a completely
stand-alone window that can be moved around the Z order independently
of the parent. There's a definite ownership based on process, though;
terminate the process (by closing the table view) and it must close
all record views first. I've done other applications where this has
not been the case - where all top-level windows are truly equal - but
not in this instance.

As an aside, that particular program is one that we are currently
using (I glance over and can see it running on one of our terminals
here), and the interface has not changed since about 2002 (actually
earlier - 2002 had a major code rewrite without much UI change).
Multiple top-level windows fulfills the Law of Least Astonishment
admirably, and has done so for a decade.

Chris Angelico
 
R

rantingrick

As varied as the applications that call on them. One example that
springs to mind: Our database front end has "table view" and "record
view", where you get one table view and from that you can view as many
records as you like. Users may choose to effectively switch from one
view to the other, or they may open up two or more record views and
have them and the table view all on screen simultaneously.
This is not
a modal dialog; it's not even a modeless dialog - it's a completely
stand-alone window that can be moved around the Z order independently
of the parent.

You can do the exact same thing with Tkinter's windows.
There's a definite ownership based on process, though;
terminate the process (by closing the table view) and it must close
all record views first. I've done other applications where this has
not been the case - where all top-level windows are truly equal - but
not in this instance.

Tkinters Toplevels ARE equal!

However in this case you should spawn a new instance of the
application "opened" at that particular table view. It's as simple as
a few command line arguments in your script.

It's like a text editor, you never want a "New" command that resets
the current document or an open command that resets the current
document and loads the file into the existing editor. Each application
instance should only create one document and stick with it until it is
closed.

Instead you want to spawn a new instance of the editor and tell the
editor (via command line arguments) to load file data (if applicable).
Simple command line arguments (of which you should be using anyway)
are the key here. All part of proper software design.
 
C

Chris Angelico

You can do the exact same thing with Tkinter's windows.

I didn't say Tkinter couldn't do this; I said that it was a good thing
to be able to do, which you earlier decried.
However in this case you should spawn a new instance of the
application "opened" at that particular table view. It's as simple as
a few command line arguments in your script.

No! Definitely not. Initializing the application includes logging in
to the database. Suppose the user had to log in again... or, worse,
suppose I transmitted the username and password via command line
arguments. No, forcing programmers into a particular coding model is a
bad idea. Let the individual programmer decide what tool is best for
what job.
It's like a text editor, you never want a "New" command that resets
the current document or an open command that resets the current
document and loads the file into the existing editor. Each application
instance should only create one document and stick with it until it is
closed.

What, never? Well, hardly ever! (As per HMS Pinafore, if you're wondering.)

Actually, I quite frequently do want exactly that. Replace the current
buffer with a new document. Keeping the previous document involves one
of two choices (maybe more, but I can't think of any off hand):

* Leave the other document visible on the screen, cluttering things up
and forcing the user to switch to the other window, close it, and then
return to his work; or
* Have the new window completely and exactly mask the old one, making
it unobvious that the previous document is actually still open,
leaving enormous possibilities for confusion.

Audacity takes the first option (at least, the Windows version that I
used five years ago did). You choose New or Open, it brings up another
window. This astonished me when I first saw it (strike one), annoys me
85% of the time and is useful only 15% (strike two), and tends to get
in the way of rapid keyboard-oriented navigation (strike three and
out). I'd much rather Audacity kept all its "stuff" in one window,
unless I explicitly asked it for another window.

For another example, look at where web browsers are going. By your
description, one instance of a browser should work with precisely one
"document" (which in this case would be a web page). That's how
browsers were in the early days, but by the early 2000s most browsers
had some form of tabs, letting you keep that application in one
window.
Instead you want to spawn a new instance of the editor and tell the
editor (via command line arguments) to load file data (if applicable).
Simple command line arguments (of which you should be using anyway)
are the key here. All part of proper software design.

Of course I could spawn a new instance. But why? Why do it? And if I
have to have a completely new copy of all the editor's state, this is
hopelessly inefficient on memory and startup work. Why should
File|Open incur such a cost? (Ameliorated if you fork() but that has
its own consequences.) But the memory cost is nothing compared to the
extra interference it puts on "mindspace".

I currently have precisely two slots in mindspace for web browsers:
Chrome and Firefox. Chrome currently has about a dozen tabs up;
Firefox about the same, but most of them are long-term status reports
that I keep handy. If I had to have 20-30 separate windows, I would
not be able to use alt-tab to find the one I want, but would have to
use some other kind of "window picker". How would you write a
user-friendly picker that can cope with myriad instances of
everything? My guess is that it'd use some kind of tree structure with
applications at one level and windows at the next. Is this not exactly
what we already have?

Chris Angelico
 
R

rantingrick

For another example, look at where web browsers are going. By your
description, one instance of a browser should work with precisely one
"document" (which in this case would be a web page). That's how
browsers were in the early days, but by the early 2000s most browsers
had some form of tabs, letting you keep that application in one
window.

Umm, if you want to see where things are "going" you should learn
about the inner workings of chrome which actually spawns a new process
for every tab created; which has the benefit of avoiding application
lock up when one page decides to crash.
I currently have precisely two slots in mindspace for web browsers:
Chrome and Firefox. Chrome currently has about a dozen tabs up;
Firefox about the same, but most of them are long-term status reports
that I keep handy. If I had to have 20-30 separate windows, I would
not be able to use alt-tab to find the one I want, but would have to
use some other kind of "window picker". How would you write a
user-friendly picker that can cope with myriad instances of
everything?

psst: it's called a notebook in GUI jargon. Again, study up on chrome
internals.
 
C

Chris Angelico

Umm, if you want to see where things are "going" you should learn
about the inner workings of chrome which actually spawns a new process
for every tab created; which has the benefit of avoiding application
lock up when one page decides to crash.

There is still one application. There's a single process which is the
master; all the other processes die if the master dies. Chrome's
isolation of tab-groups has nothing to do with the GUI design question
of whether one top-level window is allowed to do more than one thing,
which you claimed it should not.
psst: it's called a notebook in GUI jargon. Again, study up on chrome
internals.

No, that would not be what it would be called. Also, a notebook is a
very specific widget, and it's not quite identical to Chrome's or
Firefox's tabbed browsing setup; but again, that has nothing to do
with the case. The question is one of UI design.

ChrisA
 
G

Gregory Ewing

rantingrick said:
You say "root" windows are bad however any parent-child relationship
has to BEGIN somewhere.

There's no need for *toplevel* windows to be children
of anything, though.
HOWEVER any of the windows ARE in fact
instances of Tk.Toplevel[1]. So they ARE all equal because they all
have the same methods available to them.

No, they're not -- the root window is special, because
if you kill it, the whole application exits. Often that
is inconvenient.
 
G

Gregory Ewing

rantingrick said:
Most applications consist of one main window
(a Tkinter.Tk instance).

You've obviously never used a Macintosh. On the Mac, it's
perfectly normal for an application to open multiple
documents, each in its own window, with no one window
being the "main" window. Any of them can be closed (or
even *all* of them) and the application continues to run
until you explicitly quit it.
 
S

Steven D'Aprano

Gregory said:
You've obviously never used a Macintosh. On the Mac, it's
perfectly normal for an application to open multiple
documents, each in its own window, with no one window
being the "main" window. Any of them can be closed (or
even *all* of them) and the application continues to run
until you explicitly quit it.

Or a Linux GUI. I have kwrite running with 15 open windows. The application
doesn't exit until the last window is closed, and no window is privileged
over the others.

Even in Windows, the sort of MDI interface Rick seems to be describing is
less common now than it used to be -- possibly even rare.

http://en.wikipedia.org/wiki/Multiple_document_interface
 
C

Chris Angelico

Or a Linux GUI. I have kwrite running with 15 open windows. The application
doesn't exit until the last window is closed, and no window is privileged
over the others.

It's actually quite easy to implement this, even if you _are_ forced
to have one primary window. You just have an invisible primary whose
sole purpose is to "be the application", and then everything else is
secondary windows. Kinda defeats the purpose of forcing applications
to have one primary window, though.

To my thinking, there will always be one primary *thread*, and GUI
facilities are secondary to the process, never the other way around.
When the main thread exits, the process ends.

ChrisA
 

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

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top