15

I'm writing an application in Python with the Tkinter GUI framework. It listens for keyboard and mouse events, so it must have focus. When it is launched from a terminal in Ubuntu, the following code works:

from Tkinter import *

root = Tk()
root.focus_force()

def key(event):
    print "pressed", event.char

def callback(event):
    print "clicked at", event.x, event.y 

frame = Frame(root, width=100, height=100)
frame.bind("<Key>", key)
frame.bind("<Button-1>", callback)
frame.pack()
frame.focus_force()

root.mainloop()

However, when launched from a terminal in Mac OS X 10.8.4 (stock Python 2.7.2), focus is retained by the terminal emulator until the user clicks on the window. Does anyone know of a workaround for this?

Sean W.
  • 4,944
  • 8
  • 40
  • 66

3 Answers3

15

I tried this and it worked well for me:

from os import system
from platform import system as platform

# set up your Tk Frame and whatnot here...

if platform() == 'Darwin':  # How Mac OS X is identified by Python
    system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')

Of course, that'll bring your entire application to the front, not just a specific window, but after you do that, you can then use focus_force() on a specific frame or window and that'll get moved to become the frontmost of all your application windows.

For those interested, I didn't write the system() call myself. I found it in this thread on SourceForge.

The fact that I put the system() call within an if block that verifies this is running on OS X makes the solution cross platform - my understanding is that focus_force() works on all other platforms exactly as you want, and just performing it after the system() invocation wouldn't cause any problems in OS X, either.

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
2

came here wondering the same question, but I found this wise sounding answer from Kevin Walzer which suggests to use py2app:

Yes, this is standard behavior for OS X. Running an app in Terminal keeps focus in the Terminal unless you switch by clicking windows. The Command-Tab behavior is determined by the windowing system, not by a newly spawned process.

The way around this is to wrap your application up in a standard Mac app bundle using py2app. The average Mac user isn't going to launch a Python-based game from the command line.

Kevin

(from https://groups.google.com/forum/#!topic/comp.lang.python/ZPO8ZN5dx3M)

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
David Lam
  • 4,689
  • 3
  • 23
  • 34
  • You can also use [pyinstaller](http://www.pyinstaller.org/). I like it since I can make both Mac App bundles and Windows executables. – Fiver Dec 07 '13 at 19:11
-1

Do wait_visibility and event_generate help ?

eg. something like -

from Tkinter import *

root = Tk()

def key(event):
    print "pressed", event.char

def callback(event):
    print "clicked at", event.x, event.y 

frame = Frame(root, width=100, height=100)
frame.bind("<Key>", key)
frame.bind("<Button-1>", callback)
frame.pack()

frame.focus_set()

root.wait_visibility()
root.event_generate('<Button-1>', x=0, y=0)

root.mainloop()
Oblivion
  • 1,669
  • 14
  • 14