[Tutor] Tkinter dilemas - off topic
Andrzej Kolinski
AKolinski at nriindustries.com
Tue Apr 20 16:12:20 EDT 2004
Magnus,
What's your IQ, Magnus? I guess it is way above 150 (if I'm insulting you,
my apologies; I didn't mean that). I'm not a programmer, but being a
python enthusiast I'm always impressed by clarity and depth of your
messages. I don't only read them several times but also save them for
future studies:-). Thank you so much!
_/_/ _/ _/
_/ _/ _/ _/
_/_/_/_/ _/_/
_/ _/ _/ _/
_/ _/ _/ _/
Andrzej Kolinski
I fear that there is no really beginner-friendly way of writing GUI code
in Python. Tkinter isn't great, but the other GUI tool kits are thin
wrappers for C or C++ libraries where quirks caused by the underlying
language shine through. We can't really compete with VB on the beginner
level here... Will someone please write PyNewbieGui or VisualPython?
David Talaga wrote:
> global root
> root=Tk()
The global statement is meaningless here. Use global within a local
scope to declare that a certain name in that (local) scope refers to
a global variable. E.g:
>>> x = "Hello"
>>> def f():
global x
x = 'Hi'
>>> print x
Hello
>>> f()
>>> print x
Hi
There is no way you can stop local variables overriding globals like
you seem to be trying to do. On the other hand, you never assign to
the name "root" in any local scope, so you don't need that anyway.
As a general rule, try to avoid global variables. Your program is
short but still seems messy to me. Maybe you can try to clean it
up a bit. For instance, you use both "from Tkinter import *" and
"import Tkinter". Why all of Tkinter in two scopes? For clarity,
avoid using "from <something> import *".
You should also try to give all variables and functions good names.
Try to spend some time thinking about that. It will make it easier
for others to understand your code, and it might help you make it
clear for yourself what the different parts of the program are really
supposed to do. (If you can't think of a good name for a function or
variable, it's likely that it's not a very good function or variable...)
> import re
..
> sub = re.sub
..
> tmp = sub('\x0D','', i)
Don't do that! Skip the middle step and do
> import re
..
> tmp = re.sub('\x0D','', i)
A call to "re.sub" is meaningful to any experienced Python coder reading
your code. Just "sub" means that he has to look in some other place in the
code (remember that "real" programs get thousands of lines long) to figure
out that your sub is simply the sub in the re module. Also, for a Python
newbie reading "re.sub" it will be clear where to find out more about what
the sub function does.
> def doDialog():
> global result
> result = dialog()
Why this strange two step solution?
#Define the List function that displays the list of "cleaned" files
def Open():
Incorrect comments are worse than no comments... ;)
> def Clean():
> if f:
> fileName = dialog()
> in_file = open(fileName,'r').readlines()
> out_file = open(fileName + '_cleaned.txt', 'w')
> for i in in_file:
> tmp = sub('\x0D','', i)
> out_file.write(tmp)
> print 'File cleaned'
>
> if x:
> out_file.close()
> if l:
> List()
> print fileName
Huh? Neither f, x nor l are defined in this scope (or globally).
In the function where they *are* defined they all refer to Buttons,
and should all be "true" all the time. It seems these if-statements
have nothing to do in this function. Clean should only be called if
you pressed the Clean button anyway.
Have you really understood the concept of callbacks in Tkinter? You
know, the Tkinter.Button(... command = ...) thingie?
> #Make the path where the cleaned files will be stored
> if os.path.isdir("C:\\Cleaned_Files"):
> print "C:\\Cleaned_Files exists"
> else:
> os.mkdir("C:\\Cleaned_Files")
This is exactly the kind of situation where you might possibly
want global variables (but probably not the global statement) after
all. Don't repeat yourself! Note that you should have used this directory
in the Clean() function as well (and in List()?), if it's going to be
meaningful. Defining the same string like that over and over again is a
bug waiting to happen. One day you will want to move the directory, but
forget to change the code in one place. :(
So:
CLEANED_FILES_DIR = "C:\\Cleaned_Files"
..
out_file_name = os.path.join(CLEANED_FILES_DIR, fileName +
'_cleaned.txt')
out_file = open(out_file_name, 'w')
..
#Make the path where the cleaned files will be stored
if os.path.isdir(CLEANED_FILES_DIR):
print CLEANED_FILES_DIR, "exists"
else:
os.mkdir(CLEANED_FILES_DIR)
Frankly, your code smells of cargo cult programming*) ;). What I mean
is that it seems you are writing (copying?) code that you don't really
understand. That won't work. Perhaps you need to slow down a little,
and try to make something very small and elementary work, and make
sure you understand exactly what all the parts are for, and how they
interact. Then you can expand on that, a small step at a time.
It seems to me that GUI code is an area where OO code with classes
is a very suitable approach. Classes give you a good tool to retain
values (attributes of the object) between function calls, and still
keep all these values in a well defined place. But maybe it's a bit
too much to introduce that concept right now...
I might do something like below, but perhaps I'm just confusing you
by introducing a class if that is a new concept for you. Also note
that I'm far from a Tkinter guru. Anyway, don't expand further on
this unless/until you feel that you understand it completely.
Feel free to ask more questions of course...
import Tkinter
import sys
import tkFileDialog
class MyMenu:
def __init__(self, root):
# Set up menu
self.cleanButton = Tkinter.Button(root, text = "Clean File",
command = self.onCleanButton)
self.cleanButton.pack()
self.viewButton = Tkinter.Button(root, text = "View List",
command = self.onViewButton)
self.viewButton.pack()
self.exitButton = Tkinter.Button(root, text = "Exit",
command = sys.exit)
self.exitButton.pack()
self.filename = None
def openFile(self):
initDir = 'C:/windows/desktop'
filetype = [('All files', '.*')]
self.fileName = tkFileDialog.askopenfilename(initialdir=initDir,
filetypes=filetype)
def cleanFile(self):
if not self.fileName:
return
# You know what to put here...
print "Process", self.fileName
def onCleanButton(self):
self.openFile()
self.cleanFile()
def onViewButton(self):
print "View List"
# I don't quite understand what you are trying to do in "List()",
# but I suspect you want a new window for this? A Toplevel?
root = Tkinter.Tk()
MyMenu(root)
root.mainloop()
*) See http://www.science.uva.nl/~mes/jargon/c/cargocultprogramming.html
--
Magnus Lycka, Thinkware AB
Alvans vag 99, SE-907 50 UMEA, SWEDEN
phone: int+46 70 582 80 65, fax: int+46 70 612 80 65
http://www.thinkware.se/ mailto:magnus at thinkware.se
_______________________________________________
Tutor maillist - Tutor at python.org
http://mail.python.org/mailman/listinfo/tutor
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/tutor/attachments/20040420/7eaab5e4/attachment-0001.html
More information about the Tutor
mailing list