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

Rick Johnson rantingrickjohnson at gmail.com
Wed Jul 11 00:11:02 CEST 2012


I've tried to condense your code using the very limited info you have
provided. I have removed unnecessarily configuring of widgets and
exaggerated the widget borders to make debugging easier. Read below
for Q&A.

## START CONDENSED CODE ##
records = range(4)

CNF_SUBFRAME = {
    'bd':5, # rowFrame boder width.
    'relief':RIDGE,
    }

CNF_LABEL = {
    'anchor':W,
    'width':10,
    'bg':'gray',
    }

class FooFrame(tk.Frame):
    def __init__(self, master, **kw):
        tk.Frame.__init__(self, master, **kw)
        self.build_records()

    def build_records(self):
        # Should this method be called by __init__???
        # Not sure if "records" is passed-in or global???
        for n in range(len(records)):
            record = records[n]
            rowFrame = tk.Frame(self, name='-%d-'%n, **CNF_SUBFRAME)
            rowFrame.bind ('<Enter>', self.evtEnter)
            rowFrame.bind ('<Leave>', self.evtLeave)
            rowFrame.bind ('<ButtonRelease-1>',
self.evtButtonOneRelease)
            rowFrame.bind ('<ButtonRelease-3>',
self.evtButtonThreeRelease)
            rowFrame.grid (row=n+2, column=1, padx=5, pady=5)
            for i in range(4):
                lbtext = 'Label_'+str(i)
                label = tk.Label(rowFrame, text=lbtext, **CNF_LABEL)
                label.grid (row=0, column=i, sticky=NW)

    def evtEnter(self, event):
        w = event.widget
        print 'evtEnter', w.winfo_class()
        w.config(bg='magenta')

    def evtLeave(self, event):
        w = event.widget
        print 'evtLeave', w.winfo_class()
        w.config(bg='SystemButtonFace')

    def evtButtonOneRelease(self, event):
        w = event.widget
        print 'evtButtonOneRelease', w.winfo_class()
        w.config(bg='Green')

    def evtButtonThreeRelease(self, event):
        w = event.widget
        print 'evtButtonThreeRelease', w.winfo_class()
        w.config(bg='Blue')

if __name__ == '__main__':
    root = tk.Tk()
    frame = FooFrame(root, width=100, height=100, bg='red', bd=1)
    frame.pack(padx=5, pady=5)
    root.mainloop()
## END CONDENSED CODE ##


In the code sample provided, you will see that the label widgets
stacked on each row will block "click" events on the containing
"rowFrames" below them. You can get a click event (on the sub frames)
to work by clicking the exaggerated border on the frames. All the
events work properly for me, although this GUI interface seems
unintuitive even with proper borders and colors.

Fredric, I can't help but feel that you are not attacking the problem
correctly. Please explain the following questions in detail so that i
may be able to provide help:

Q1. You have subclassed a Tkinter.Frame and you are building "rows" of
sub-frames into this toplevel frame; with each row holding
horizontally stacked label widgets. Okay, I can see a need to wrap up
a "RowFrame" object, but i don't see a need to create a
"RowFrameFactory". Can you explain this design decision?

Q2. It seems odd to me that you want to engage the "rowFrame" widgets
via events but NOT the Label widgets. Can you explain this design
decision?




More information about the Python-list mailing list