tkinter: Disable the focus on each widget

Question:

With tkinter you can deactivate the focus of a single widget

tk.Button(root, takefocus=False)

Is it also possible to disable this for all widgets at once?

Edit:
By "all" I mean all tk and ttk widgets present in the window.

Asked By: Fire Cube

||

Answers:

takefocus is a standard option in tkinter and ttk. So all you have to do is to recursively loop over the widgets and configure them as desired. The function should look like this:

def disable_takefocus(widget):
    for w in widget.winfo_children():
        w.configure(takefocus=False)
        disable_takefocus(w) 
disable_takefocus(root)

Be aware this should be called AFTER you created ALL FINAL widgets. If you dynamically add and delete widgets to your window, it won’t help. A general solution for ttk and tkinter does not seem to be possible due the different style engines. For tkinter widgets you could use option_add, but for ttk it is a different animal. Ttk uses a style engine with a fallback chain. It is not easy to spot where the option will be garbed from especially if you take the different themes into account.

For ttk it seems to be the easiest to define styles for each widget.

Of course you could bind ‘<Configure>’ to all widgets or just containers and call this or a similar function to force that option to be False. But this way you produce a overhead in your event queue. This does not look like a good trade of that can be avoided with a few lines of code.


There is another technique you might not know about and can help to have default options. The options are parsed as keyword arguments therefor you could define a dictionary with default values and unpack them in the constructor interface. As an example:

defaults = {
    'takefocus' : False,
    'background' : '#000000',
    'foreground' : '#ffffff',
    }
label = tk.Label(root, **defaults)
label.pack()
button = ttk.Button(root, **defaults)
button.pack()
Answered By: Thingamabobs

You can use winfo_children() function to find all children of the window.
And you can use configure() function for each child.

from tkinter import *
window=Tk()
btn=Button(window, text="Button1")
btn.place(x=120, y=60)
btn=Button(window, text="Button2")
btn.place(x=120, y=100)
window.title('Disable the focus on each widget')
window.geometry("300x200+10+10")

for child in window.winfo_children():
    child.configure(takefocus=False)
window.mainloop()
Answered By: pyMorgan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.