如何为父级及其所有子级禁用takefocus?

时间:2017-11-18 10:57:01

标签: python tkinter tcl tk

我可以为一个小部件编写widget.configure(takefocus=False)来实现我想要的。但有没有办法可以轻松禁用对父窗口小部件及其所有子窗口的关注,而不是遍历每个子节点并逐个禁用?

以下是一个例子:

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


class BasicOperations(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        operations = "+-*/"
        self.buttons = list()
        for op in operations:
            self.buttons.append(tk.Button(self, text=op))
        #configure the geometry
        for i in range(len(self.buttons)):
            self.buttons[i].grid()


if __name__ == '__main__':
    root = tk.Tk()
    basic_ops = BasicOperations(root)
    basic_ops.pack()
    root.mainloop()

我尝试在self.configure(takefocus=False)内调用__init__,但它没有禁用其下方按钮的焦点拍摄。

2 个答案:

答案 0 :(得分:2)

焦点决策以递归方式强制执行,因为包含小部件(通常是框架)即使在其包含的小部件确实占据焦点时也不会引起焦点是很正常的。但是,takefocus属性不需要是静态的东西;它可以设置为一个返回布尔值的callable,这样无论何时进行焦点遍历决策,callable都会决定当前的widget是否应该给它一个焦点。这意味着你所要做的就是提供一个callable,它从一个在感兴趣的组中共同的变量返回一个值。

您有一个方便的类,它提供了合理的范围,因此类实例的方法可以完美地调用。

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


class BasicOperations(tk.Frame):
    def _take_focus_handler(self):
        return self._group_focusable

    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self._group_focusable = True
        operations = "+-*/"
        self.buttons = list()
        for op in operations:
            self.buttons.append(tk.Button(self, text=op,
                                        takefocus=self._take_focus_handler))
        #configure the geometry
        for i in range(len(self.buttons)):
            self.buttons[i].grid()

    def set_group_focusable(self, value=True):
        self._group_focusable = value
        # Note that you might also want to defocus the widgets if the focus is
        # already in the group, but you didn't ask for that...


if __name__ == '__main__':
    root = tk.Tk()
    basic_ops = BasicOperations(root)
    basic_ops.pack()
    root.mainloop()

答案 1 :(得分:1)

您可以分两步完成解决方案:

  1. 禁用父窗口小部件的takefocus
  2. 遍历该父窗口小部件的children并为其中每个窗口小部件停用takefocus

    for child in self.winfo_children():
        child.configure(takefocus=False)