Tkinter.event.widget: handler gets name instead of widget.

rantingrickjohnson at rantingrickjohnson at
Sun Jul 15 05:10:27 CEST 2012

On Thursday, July 12, 2012 1:53:54 PM UTC-5, Frederic Rentsch wrote:

> The "hit list" is a table of investment titles (stock, funds, bonds)
> that displays upon entry of a search pattern into a respective template.
> The table displays the matching records: name, symbol, ISIN, CUSIP, Sec.
> Any line can be click-selected. So they are to look like buttons.

Hmm. If they "appear" like a button widget anyway, then why not just use a button widget?

> Representing the mentioned names and id codes in Label widgets was the
> simplest way I could come up with to align them in columns, admittedly
> without the benefit of much experience. But it does look good. the
> layout is fine.

But is it really the "simplest"? :)

import Tkinter as tk
from Tkconstants import *

colWidths = (5,10,30,5)
N_COLS = len(colWidths)
N_ROWS = 6

root = tk.Tk()
for r in range(N_ROWS):
    # Create some imaginary text to display in each column.
    # Also try using string methods "center" and "rjust" to
    # see alternative justification of text.
    lst = [str(r).ljust(colWidths[r]) for r in range(N_COLS)]
    b=tk.Button(root, text=''.join(lst))
    b.pack(padx=5, pady=5)
## END CODE ##

You could easily expand that into something reusable.

Now. If you need to place fancy borders around the texts, or use multiple fonts, or use images, or blah blah blah... then you may want to use the "canvas items" provided by the Tkinter.Canvas widget INSTEAD of buttons. 

With the canvas, you can create a simple rectangle (canvas.create_rectangle) that represents a button's outside dimension and give it a "button styled" border. Then you can bind click events to mimic the button press action. Then you can place canvas_text items on top of that fake button and configure them to be invisible to click events. These text items will not interfer like the Tkinter.Label widgets are currently doing. 

However, i would suggest the Tkinter.Button solution is the easiest by far.

> I find the Tkinter system quite challenging. Doing a layout isn't so
> much a matter of dimensioning and placing things as a struggle to trick
> a number of automatic dimensioning and placing mechanisms into
> obliging--mechanisms that are rather numerous and hard to remember.

I don't think i agree with that assessment. 

I find the geometry management of Tkinter to be quite powerful whilst being simultaneously simplistic. You only have three main types of management: "Grid", "Place", and "Pack". Each of which has a very specific usage. One caveat to know is that you can NEVER mix "Grid" and "Pack" in the same container widget! I find myself using grid and pack the most, with grid being at the top of the list.

Now, i will agree that grid can be confusing at first until you understand how to "rowconfigure" and "columnconfigue" the containing widget (be it a frame or a toplevel). There is also the "sticky" attribute to consider. 

But all in all, i would say the most difficult part of the Tkinter geometry management API is coming to grips as to which of the three geometry managers is the best choice for the particular problem at hand -- and you will find yourself using more than one manager in a single GUI app!

But i don't see you solving this problem by stacking one widget on another. I believe it's time to seek out a new solution.

EASY: Using rows of Tkinter.Button coupled with a per-formatted text string.
ADVANCED: Creating "pseudo buttons" on a canvas and stacking text objects (or whatever you like) on them.

More information about the Python-list mailing list