0

I'm running Python 2.7.9 on a Mac. I've been unable to figure out why it is when I run my programs that only the Entry Widgets highlight each time I hit the Tab key to move to the next widget. Following is some test code. When I run the script and hit the Tab key, the first entry field is highlighted. The next time I hit the Tab key, the second entry field is highlighted. However, when I hit the tab key to move to the Button Widget, the Button is receiving the focus but there is not highlight to visually indicate to the user the focus.

The OptionMenu widget is skipped altogether, which is also a mystery. Both the radiobutton and the checkbox receives focus, just like the button widget, and again no highlight is present.

I've tried a variety of .config() arrangements to no avail. What am I missing?

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()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
rcronrath
  • 3
  • 4

2 Answers2

1

It sounds like you need to configure OS X for "Full Keyboard Access" to allow Tab to focus on all UI controls (versus just text boxes and lists).

In Yosemite (10.10), this setting can be found under System Preferences > Keyboard > Shortcuts, and can be toggled with Control+F7. Note that has nothing to do with Python, and will occur system-wide.

EDIT

So after doing some more testing, there appears to be some issues with the actual highlighting of certain widgets using tk on a Mac. Below is a condensed version of your original sample with some minor modifications for simplicity.

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

With full keyboard access enabled as previously mentioned, I can verify that the button does indeed receive focus: on the third tab, after the first two entry widgets, hitting <space> "clicks" the button and prints to stdout. However there is no visual indication that the button is selected.

Changing the button from a tk.Button to a ttk.Button "fixes" this, and does indeed show the normal "selection" frame around the button when tabbing through the UI.

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

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

I have no idea why this is, and I don't know what the consensus about tkinter.ttk is, but I prefer ttk to "plain" tk as it seems to produce widgets which appear more "native" to OS X in my experience. Note I also removed the bind statement, and am reporting my result using the OS X default of space to activate UI elements with full keyboard access enabled.

More on ttk here. Note also that not all tk widgets have a ttk implementation, and that there are also some ttk widgets which do not exist in tk.

Lastly below find the "ttk" version of the original snippet.

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

Hope this helps.

chdorr
  • 288
  • 3
  • 8
  • I really thought that might work chdorr but alas it did not. I tried it on a few different scripts, including the attached script and I tried restarting my system after setting up "Full Keyboard Access". Thanks for your input. – rcronrath Apr 29 '15 at 03:22
  • Hi rcronrath, I have edited my answer with (hopefully) some more info on why this may be the case and how to fix it. – chdorr Apr 29 '15 at 04:18
  • chdorr, that did it. Thank you. I really, REALLY appreciate your time and help. Looks like I'll be getting acquainted with ttk. Thanks again. – rcronrath Apr 29 '15 at 20:55
  • Glad to help rcronrath. "Getting familiar" with `ttk` isn't a huge deal as you basically just replace `tk` with `ttk` where applicable. There are some other differences (namely, styling widgets), but I think the Python docs address these pretty clearly. – chdorr Apr 29 '15 at 21:22
0

Try changing the background and highlightbackground colors as below but the problem is possibly because of the way the program is indented --> run the second code block.

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()
  • In addition to correcting the indent, I've tried bg and activebackground with no change. I noticed in another question today that someone mentioned that Button height could not be change on a Mac. Could it be possible that highlighting for Buttons isn't available on a Mac either? – rcronrath Apr 27 '15 at 04:19