First Tkinter script: requesting comments

Francesco Bochicchio bieffe62 at gmail.com
Sun May 23 03:50:43 EDT 2010


On 21 Mag, 23:51, Bart Kastermans <bkast... at gmail.com> wrote:
> I wrote a first script using Tkinter.  As I am new to its
> use, I am only just feeling my way around.  I would very
> much like comments on the design of the script (and in fact
> any other comments on my code would also be very welcome).
>
> I have it posted (with syntax coloring) at:
>
> http://kasterma.wordpress.com/2010/05/21/first-experiments-with-tkinter/
>
> But will also include it here for convenience.
>
> Thanks for any help,
>
> Best,
> Bart
>
> ***********************
>
> #!/usr/bin/env python
> #
> # Getting a list of students and grades displayed so that grades can
> # be updated, and we poll these changes (so that in the future we can
> # act on it).
> #
> # Bart Kastermans,www.bartk.nl
>
> """
> Design of the window
>
>       +-------------------------------------------------------------+
>       |  root                                                       |
>       |  +------------------------------------------------------+   |
>       |  | title_frame                                          |   |
>       |  |  +------------------------------+                    |   |
>       |  |  | Label(title)                 |                    |   |
>       |  |  |                              |                    |   |
>       |  |  +------------------------------+                    |   |
>       |  +------------------------------------------------------+   |
>       |  +------------------------------------------------------+   |
>       |  | exam_grades_frames                                   |   |
>       |  |  +-------------------------------------------------+ |   |
>       |  |  | Frame(ex)                                       | |   |
>       |  |  | +--------------------+  +---------------------+ | |   |
>       |  |  | | Entry(name)        |  | Entry(grade)        | | |   |
>       |  |  | |                    |  |                     | | |   |
>       |  |  | +--------------------+  +---------------------+ | |   |
>       |  |  +-------------------------------------------------+ |   |
>       |  |                                                      |   |
>       |  +------------------------------------------------------+   |
>       |                                                             |
>       |                 +---------------------+                     |
>       |                 | quit_button         |                     |
>       |                 |                     |                     |
>       |                 +---------------------+                     |
>       +-------------------------------------------------------------+
>
> """
>
> from Tkinter import *
>
> # global info for this specific example
>
> # four students
> no_stud = 4
> exam_grades = [1,2,3,4]
> names = ["Ben", "Jim", "James", "Mel"]
> # upper bound for name length
> max_name_len = max (map (len, names))
>
> # set up root window
> root = Tk()
> root.geometry ("400x400")
>
> exam_grades_string = map (lambda x: StringVar (root,str (x)), exam_grades)
>
> names_string = map (lambda x: StringVar (root, x), names)
>
> def setup ():
>     """ setup the window with the list of students.
>
>     This is test-code to figure out what the app finally should look
>     like.
>     """
>
>     # title frame, with title Grade Correction in it
>     title_frame = Frame(root)
>     title_frame.pack (fill=X)
>
>     w = Label (title_frame, text = "Grade Correction", font = ("Helvetica", 25))
>     w.pack (side=LEFT)
>
>     # from to hold the list of grades
>     exam_grades_frame = Frame (root)
>     exam_grades_frame.pack (fill=BOTH)
>
>     exam_label = Label (exam_grades_frame, text="EXAMS")
>     exam_label.pack ()
>
>     # set up the list of grades
>     for i in range (0,no_stud):
>         # a frame per student
>         ex = Frame (exam_grades_frame)
>         ex.pack ()
>         # name on the left
>         name = Entry (ex, textvariable=names_string[i], width=max_name_len+2)
>         name.config (state=DISABLED)
>         name.pack (side=LEFT)
>         # grade next to it
>         grade = Entry (ex, textvariable=exam_grades_string [i], width=4)
>         grade.pack (side=LEFT)
>
>     # button to quit the application
>     qb = Button (root)
>     qb ['text'] = "quit"
>     qb ['command'] = root.quit
>     qb.pack ()
>
> def to_int (st):
>     """ helper function to convert strings to integers.
>
>     Empty string represents 0.
>     """
>     if len (st) == 0:
>         return 0
>     else:
>         return int (st)
>
> def get_curr_grades ():
>     """ extract the grades from exam_grades_string.
>
>     exam_grades_string consists of StringVar that get updated when the
>     fields are updated in the GUI.
>     """
>     grades = []
>     for i in range (0, no_stud):
>         grades.append (exam_grades_string [i].get())
>     return grades
>
> # get the current grades
> curr_grades = map (to_int, get_curr_grades ())
>
> def poll_exams ():
>     """ function that keeps polling the current grades, looking for changes"""
>     global curr_grades
>     new_grades = map (to_int, get_curr_grades ())
>     if new_grades != curr_grades:
>         print new_grades
>         curr_grades = new_grades
>     root.after( 250, poll_exams)
>
> # window setup
> setup ()
>
> # start the polling
> poll_exams ()
>
> # start the eventloop
> root.mainloop ()
>
> # do cleanup
> root.destroy ()
> sys.exit ()

It looks fine to me, except that I would do it a bit more OOP-style
(can't stand the globals very much).

Also, I would use labels instead of disabled text fields for student
names, since they don't need to be edited.
Add maybe tray to align the name and grade widgets in a 2x4 matrix
using .grid() instead of .pack()
( see  http://effbot.org/tkinterbook/grid.htm )

One thing I don't understand, is why you need to 'poll' continuously
for changes, except for demo purpose.
If this is supposed to be a window for user to enter data into the
program, the standard practice is to have a
separate window (not the main one), with  apply and cancel buttons,
where both buttons close the window but only
the apply button register the change. So you need to do the stuff you
do in the poll_exams function only in the
callback of the apply button.

On the python side, you don't need no_stud variable since you can do
len(names_string). And maybe have single list
of (name, grade) pairs, so youl loop would become something like:
       for i, (name, grade) in enumerate( names_and_grades_list )  :
            # use name instead of names_string[i]
            # use grade instead of exam_grades_string[i]

Although this could slightly complicate the upgrade of grades. The
usage of a small class StudentData could be in order, too.




Ciao
-------
FB



More information about the Python-list mailing list