Tkinter only: table widget with canvas...

John Posner jjposner at optimum.net
Sat Jul 11 00:01:06 CEST 2009


Hi --
>
> a) Assume I would have some different widgets to add per row. How
>     do I get the maximum row height?

If you are placing widgets in a table like this:

  w.grid(row=a, column=b)

... where the *master* of widget "w" is a Tkinter.Frame named 
"table_frm", then you can determine the height of row N like this:

   table_frm.grid_bbox(column=0, row=N)

Quoth the grid_bbox() documentation (with the object name changed for 
clarity):

    Returns a 4-tuple describing the bounding box of some or all
    of the grid system in widget |/|table_frm|/|. The first two numbers 
returned
    are the /|x|/ and /|y|/ coordinates of the upper left corner of the 
area,
    and the second two numbers are the width and height.


So the final member of the 4-tuple is the height you want.
>
> b) Assume something like a label in one column. The length of all
> texts
>     in a column will differ. How do I choose the maxium column width?

The third member of grid_bbox() 4-tuple is the cell-width. So just find 
the maximum of these values:

   table_frm.grid_bbox(column=0, row=0)[2]
   table_frm.grid_bbox(column=1, row=0)[2]
   table_frm.grid_bbox(column=2, row=0)[2]
   ...

>
> c) Placing headers in a canvas does not look like a good idea because
>     I don't want to scroll the headers. Am I right?
>     c.1) How do I place a none scrollable header in a canvas?  or
>     c.2) How do I place all headers outside the canvas correctly above
> the relating column?
>

"c.2" is what you want. Again, if the table is in a Tkinter.Frame named 
"frm", you want to create an outer frame, then pack a header frame and 
the table frame into it, vertically:

    rt = Tk()
    outer_frm = Frame(rt)
    outer_frm.pack(expand=True, fill=BOTH)
    header_frm = Frame(outer_frm, height=25)
    header_frm.pack(side=TOP)
    table_frm = Frame(outer_frm)
    table_frm.pack(side=TOP)


(For scrolling, consider making "table_frm" a Pmw.ScrolledFrame instead 
of a Tkinter.Frame.)

As for getting the heading labels correctly placed above the columns, 
pack correctly-sized subframes (Tkinter.Frame's) into "header_frm". To 
determine the size of a column, use grid_bbox() again:

    BBOX_WIDTH_COMPONENT = 2
    header_subfrm = Frame(header_frm, relief=GROOVE, bd=2)
    header_subfrm['width'] = \
         table_frm.grid_bbox(column=N, row=0)[BBOX_WIDTH_COMPONENT]
  
Then, use place() to center a label within the subframe:

    header_label = Label(header_subfrm, text="Heading")
    header_label.place(relx=0.5, rely=0.5, anchor=CENTER)

There's a working app at http://cl1p.net/tkinter_table_headers/

-John





More information about the Python-list mailing list