Tkinter:小部件未在 <Tab> 事件中突出显示

Tkinter: widgets not highlighting on <Tab> event

我正在 运行宁 Python 2.7.9 Mac。我一直无法弄清楚为什么当我 运行 我的程序时,每次我按下 Tab 键移动到下一个小部件时,只有 Entry Widgets 突出显示。以下是一些测试代码。当我 运行 脚本并按下 Tab 键时,第一个输入字段会突出显示。下次我按下 Tab 键时,第二个输入字段会突出显示。但是,当我按下 Tab 键移动到 Button Widget 时,Button 正在接收焦点,但没有高亮显示以直观地向用户指示焦点。

OptionMenu 小部件被完全跳过,这也是一个谜。 radiobutton 和 checkbox 都获得焦点,就像按钮小部件一样,同样没有高亮显示。

我试过各种 .config() 安排都无济于事。我错过了什么?

from tkinter import *

class App:

    def __init__(self, master):
        frame = Frame(master)
        frame.grid()

        #Tests to make sure that Button receives focus.
        def yup(self):
            print "yup"

        entry1 = Entry(frame)
        entry1.pack()

        entry2 = Entry(frame)
        entry2.pack()

        button1 = Button(frame, text="Test")
        button1.pack()
        button1.bind('<Return>', yup)

        var1 = IntVar()
        c = Checkbutton(frame, text="Expand", variable=var1)
        c.pack()

        var2 = StringVar()
        radio = Radiobutton(frame, text="Test", variable=var2, value=1)
        radio.pack()

        var3 = StringVar()
        optionmenu1 = OptionMenu(frame, var3, "one", "two", "three")
        optionmenu1.pack()


root = Tk()
root.geometry('400x400+0+0')
app = App(root)

root.mainloop()

尝试如下更改背景和突出显示背景颜色,但问题可能是因为程序缩进的方式 --> 运行 第二个代码块。

top=Tk()

## active background
Button(top, text="Quit", bg="lightblue", activebackground="orange",
       command=top.quit).grid(row=1)
top.mainloop()

##--------------- note the 3 lines that have been changed ---------
class App:

  ## function was not indented
  def __init__(self, master):
    frame = Frame(master)
    frame.grid()

    entry1 = Entry(frame)
    entry1.pack()
    entry1.focus_set()

    entry2 = Entry(frame)
    entry2.pack()

    button1 = Button(frame, text="Test")
    button1.pack()
    ## function called incorrectly
    button1.bind('<Return>', self.yup)

    var1 = IntVar()
    c = Checkbutton(frame, text="Expand", variable=var1)
    c.pack()

    var2 = StringVar()
    radio = Radiobutton(frame, text="Test", variable=var2, value=1)
    radio.pack()

    var3 = StringVar()
    optionmenu1 = OptionMenu(frame, var3, "one", "two", "three")
    optionmenu1.pack()

    Button(frame, text="Quit", bg="orange", command=master.quit).pack()

  ## function indented too far
  #Tests to make sure that Button receives focus.
  def yup(self, args):
      print "yup"


root = Tk()
root.geometry('400x400+0+0')
app = App(root)

root.mainloop()

听起来您需要为 "Full Keyboard Access" 配置 OS X 以允许 Tab 专注于所有 UI 控件(而不是仅文本框和列表)。

在 Yosemite (10.10) 中,可以在“系统偏好设置”>“键盘”>“快捷方式”下找到此设置,并且可以使用 Control+F7 切换。请注意,这与 Python 无关,并且会在系统范围内发生。

编辑

因此,在进行更多测试后,在 Mac 上使用 tk 的某些小部件的实际突出显示似乎存在一些问题。以下是您的原始样本的浓缩版,为简单起见做了一些小的修改。

import Tkinter as tk
import ttk # more on this in a minute

class App(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)

        self.master = master

        entry1 = tk.Entry(self)
        entry1.pack()

        entry2 = tk.Entry(self)
        entry2.pack()

        button1 = tk.Button(self, text="Test", command=self.yup)
        button1.pack()

    def yup(self):
        print("yup")

    # ...

root = tk.Tk()
app = App(root).pack()

root.mainloop()

如前所述启用全键盘访问后,我可以验证该按钮确实获得了焦点:在第三个选项卡上,在前两个输入小部件之后,点击 <space> "clicks" 按钮并打印到标准输出。但是,没有视觉指示表明按钮已被选中。

将按钮从 tk.Button 更改为 ttk.Button "fixes" 这确实在通过 UI.

button1 = tk.Button(self, text="Test", command=self.yup)

# change this to:
button1 = ttk.Button(self, text="Test", command=self.yup)

我不知道这是为什么,我不知道关于 tkinter.ttk 的共识是什么,但我更喜欢 ttk 而不是 "plain" tk根据我的经验,它似乎产生了 "native" 到 OS X 的小部件。请注意,我还删除了 bind 语句,并使用 OS X 默认值 space 来报告我的结果,以激活启用全键盘访问的 UI 元素。

有关 ttk here 的更多信息。另请注意,并非所有 tk 小部件都有 ttk 实现,并且还有一些 ttk 小部件在 tk.

中不存在

最后在下面找到原始片段的“ttk”版本。

import Tkinter as tk
import ttk

class App(ttk.Frame):

    def __init__(self, master):

        ttk.Frame.__init__(self, master)

        self.master = master

        entry1 = ttk.Entry(self)
        entry1.pack()

        entry2 = ttk.Entry(self)
        entry2.pack()

        button1 = ttk.Button(self, text="Test", command=self.yup)
        button1.pack()

    def yup(self):
        print("yup")

    # ...

root = tk.Tk()
app = App(root).pack()

root.mainloop()

希望对您有所帮助。