2

I am having a hard time understanding the focus events for Entry and Textbox fields in Python version 3 using Tk. I eventually need to validate an Entry box on lost focus if I click a radio option or a button.

If you run the code below then (which serves only to demonstrate Focus issues not the validation i require elsewhere), place the cursor in either of the top row Entry boxes and click between the other widgets, the only time FocusIn and Focus out events occur are on the widgets that accept input ie Text/Entry boxes.

Clicking the button or the radio options, the cursor remains in the Entry or Textbox widgets. Why when i have clearly focused on a radio option or the button.

I have tried .bind FocusIn/Out events and still no joy. if anyone has an explanation I would be intrigued to know why and possibly how i can overcome it.

from tkinter import *

root = Tk()

root.title("My Widgets")
root.update_idletasks()
root.geometry("350x200+10+300")
root.attributes("-toolwindow",1)
root.resizable(width=FALSE, height=FALSE)
root.config(bg="blue")

# function below output to the console and label the focus results
def Validate(a,b,c,d,e,f,g,h):

    text = g + ' on ' + h
    lblOutputVar.set(text)
    print(f,g,h)
    return True

var = IntVar()
lblOutputVar = StringVar()

vcmd=(root.register(Validate),'%d','%i','%P','%s','%S','%v','%V','%W')

entryOne = Entry(root, name = 'entryBoxOne')
entryOne.config(validate = 'all',vcmd=vcmd)
entryOne.grid(row=1, column=1,padx=(0,0),pady=(10,10),ipady=(1), sticky=E+W)

entryTwo = Entry(root, name = 'entryBoxTwo')
entryTwo.config(validate = 'all',vcmd=vcmd)
entryTwo.grid(row=1, column=2,padx=(10,0),pady=(10,10),ipady=(1), sticky=E+W)

txtBox = Text(root, name = 'textBox', width=10, height=1, takefocus = 0)
txtBox.grid(row=5, column=1, sticky=E+W)

aButton = Button(root, text = 'Click Me!', takefocus=1)
aButton.grid(row=5, column=2)

lblOutput = Label(root, name = 'labelOutput', width=20, height=2, textvariable=lblOutputVar)
lblOutput.grid(row=10, column=1, columnspan =2, pady=(5,0), sticky=E+W)

radioOne = Radiobutton(root, anchor = 'w', text = 'One', variable = var, value = 1, takefocus = 1)
radioOne.grid(row=2, column=1, sticky=E+W)
radioTwo = Radiobutton(root, anchor = 'w', text = 'Two', variable = var, value = 2, takefocus = 1)``
radioTwo.grid(row=3, column=1, sticky=E+W)

root.mainloop()
Cœur
  • 37,241
  • 25
  • 195
  • 267
Dr Jeep
  • 43
  • 3

1 Answers1

0

The explanation is simply that tkinter buttons and radiobuttons aren't given focus when you click on them. If you want that to happen, you need to set up a binding to explicitly give them the focus.

Your other option is to use a ttk radiobutton which does get focus. It's unfortunate that the two different radiobuttons have different behavior.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • OK, thank you for clearing that up. I suppose it is just one of those idiosyncrasies that must be circumnavigated. It intrigues me that the option to let a button 'takefocus' is available for keyboard navigation on a form, weird n'est-ce pas. – Dr Jeep Dec 01 '16 at 05:14
  • @DrJeep: you need to be able to interact with a button if you can't use a mouse, and the only way to do that is if the button can get keyboard focus. It's an accessibility thing. What I think is weird is for a button-like widget to take focus when you click on it -- that's one area where I think ttk got things very wrong. – Bryan Oakley Dec 01 '16 at 07:49