Tkinter binding question

rantingrickjohnson at gmail.com rantingrickjohnson at gmail.com
Tue Jun 19 22:19:59 EDT 2012


On Tuesday, June 19, 2012 10:55:48 AM UTC-5, Frederic Rentsch wrote:
> If I copy your event descriptors into my program, the button-release
> callback still fails. It works in your code, not in mine. Here is what
> my code now looks like. It is somewhat more complicated than yours,
> because I bind Frames holding each a line (line_frame) and each frame
> contains a few Labels side by side. The idea is to achieve a table with
> vertically aligning columns each line of which I can click-select. (Is
> there a better way?)
> 
>    for line_frame in ...:
>       line_frame.bind ('<Enter>', self.color_selected)
>       line_frame.bind ('<Leave>', self.color_selectable)
>       line_frame.bind ('<ButtonRelease-1>', self.pick_record)
>       line_frame.bind ('<ButtonRelease-3>', self.info_profile)
>       line_frame.grid (row = n+1, column = 0)
>       for i in self.range_n_fields:
>          field = Label (line_frame, width = ..., text = ...    
>          field.grid (row = 0, column = i, sticky = W)
>       ...
> 
>    def color_selected (self, event):
>       print 'hit list.color_selected ()'
> 
>    def color_selectable (self, event):
>       print 'hit list.color_selectable ()'
> 
>    def pick_record (self, event):     # Nver gets called
>       print 'hit list.pick_record ()'
> 
>    def info_profile (self, event):    # Never gets called
>       print 'hit list.info_profile ()'

Events only fire for the widget that currently has "focus". Frames, labels, and other widgets do not receive focus simply by hovering over them. You can set the focus manually by calling "w.focus_set()" -- where "w" is any Tkinter widget. I can't be sure because i don't have enough of your code to analyze, but I think you should bind (either globally or by class type) all "Enter" events to a callback that sets the focus of the current widget under the mouse. Experiment with this code and see if it is what you need:

## START CODE ##
from __future__ import print_function
import Tkinter as tk

def cb(event):
    print(event.widget.winfo_class())
    event.widget.focus_set()

root = tk.Tk()
root.geometry('200x200+20+20')
for x in range(10):
    w = tk.Frame(root, width=20, height=20,bg='red')
    w.grid(row=x, column=0, padx=5, pady=5)
    w = tk.Frame(root, width=20, height=20,bg='green', highlightthickness=1)
    w.grid(row=x, column=1, padx=5, pady=5)    
    w = tk.Button(root, text=str(x))
    w.grid(row=x, column=2, padx=5, pady=5)
root.bind_all("<Enter>", cb)    
root.mainloop()
## END CODE ##

You will see that the first column of frames are recieving focus but you have no visual cues of that focus (due to a default setting). In the second column you get the visual cue since i set "highlightthicness=1". The third column is a button widget which by default has visual focus cues.

Is this the problem? 

PS: Also check out the "w.bind_class()" method.

> Incidentally, my source of inspiration for chaining event descriptors
> was the New Mexico Tech Tkinter 8.4 reference, 

That's an excellent reference BTW. Keep it under your pillow. Effbot also has a great tutorial.



More information about the Python-list mailing list