【问题标题】:Tkinter: widgets not highlighting on <Tab> eventTkinter:小部件未在 <Tab> 事件上突出显示
【发布时间】:2015-07-04 13:36:13
【问题描述】:

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

完全跳过了 OptionMenu 小部件,这也是一个谜。单选按钮和复选框都接收焦点,就像按钮小部件一样,并且再次没有突出显示。

我尝试了各种 .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()

【问题讨论】:

  • 我只导入 tkinter *
  • 在主循环之后有root.destroy() 的目的是什么?没有意义,它会给你一个错误。
  • 你是对的。我更新了代码。您知道为什么突出显示不起作用吗?

标签: python tkinter widget


【解决方案1】:

尝试如下更改背景和高亮背景颜色,但问题可能是由于程序缩进的方式 -> 运行第二个代码块。

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()

【讨论】:

  • 除了更正缩进之外,我还尝试了 bg 和 activebackground,没有任何变化。我今天在另一个问题中注意到有人提到在 Mac 上无法更改按钮高度。是否有可能在 Mac 上也无法突出显示按钮?
【解决方案2】:

听起来您需要为"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()

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

将按钮从 tk.Button 更改为 ttk.Button 可以“修复”此问题,并且在通过 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 而不是“普通”tk,因为它似乎生成的小部件看起来更“原生” “根据我的经验,对于 OS X。请注意,我还删除了 bind 语句,并使用 OS X 默认的 space 来报告我的结果,以激活启用全键盘访问的 UI 元素。

更多关于ttkhere。另请注意,并非所有tk 小部件都有ttk 实现,还有一些ttk 小部件在tk 中不存在。

最后在下面找到原始sn-p的“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()

希望这会有所帮助。

【讨论】:

  • 我真的认为这可能会起作用 chdorr 但可惜它没有。我在几个不同的脚本上进行了尝试,包括附加的脚本,并在设置“全键盘访问”后尝试重新启动系统。感谢您的意见。
  • 您好,rcronrath,我已经编辑了我的答案,并(希望)提供了更多关于为什么会出现这种情况以及如何解决它的信息。
  • chdorr,做到了。谢谢你。我真的非常感谢您的时间和帮助。看来我会熟悉 ttk。再次感谢。
  • 很高兴帮助 rcronrath。 “熟悉”ttk 并不是什么大不了的事,因为您基本上只需在适用的情况下将tk 替换为ttk。还有一些其他差异(即样式小部件),但我认为 Python 文档非常清楚地解决了这些问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-21
  • 2021-05-29
  • 2011-04-16
  • 2019-04-23
  • 2019-03-15
相关资源
最近更新 更多