I use Python a lot. Python 2.5.1 to be specific. And inside Python is TkInter, which, with a little work, will give you a handy way to put a GUI together. But there are problems. To say that TkInter is poorly supported and poorly documented under OSX is to understate the case rather dramatically. So you’re left to Google for answers, and mostly, they aren’t to be found — or if they are, they aren’t obvious or easily found. So I’m going to provide some answers here that have taken me quite some time to collect, and hopefully keyword and title them so that a Google search will actually get you to the solution you need sooner rather than as much later as it did me!
The first thing is that if you launch a TkInter window from the command line, it will obstinately, and stupidly, show up behind your terminal window. Searching the net for an answer, all you find is “this is normal behavior.” You know what? It doesn’t matter that it’s normal — it’s bloody stupid. If you launch a GUI, it’s because you intend to interact with it. If it opens behind the window you launched it from… stupid. So here’s the answer you’re looking for. It’s not reasonable that you have to do this, but is easy, and it works. Just before you go to root.mainloop()
, you want to add this happy little fix:
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
Python won’t do it. TkInter won’t do it. By by Darwin, the Finder will.
Ok, next, the TkInter Listbox. Most examples tell you to use the pack() method because pack is easy. Then there are all these general notes about using sticky=N+S+E+W to make the listbox stretch with the window. Yeah. Except pack() doesn’t support sticky. Nice, eh? So, the answer is, don’t use pack. Rather than explain it all, please let me gift you with some code; most of it came from elsewhere, but I’ve prodded it to do a little more — support double clicks on the list, have an OK button if you’re a one-click kind of person… anyway, it’s handy and I truly hope you’ll find it useful. Here you go:
import Tkinter as tk
import os
class ScrolledList(tk.Listbox):
def __init__(self, master, **kw):
self.sel=""
self.frame = tk.Frame(master)
self.frame.rowconfigure(0, weight=1)
self.frame.columnconfigure(0, weight=1)
self.hbar = tk.Scrollbar(self.frame, orient=tk.HORIZONTAL)
self.block = tk.Frame(self.frame, width=18, height=18)
self.block.grid(row=1, column=1)
self.vbar = tk.Scrollbar(self.frame, orient=tk.VERTICAL)
kw.setdefault('activestyle', 'none')
kw.setdefault('highlightthickness', 0)
if 'pack' in kw.keys() and kw.pop('pack') == 1:
self.frame.pack(fill=tk.BOTH, expand=1)
tk.Listbox.__init__(self, self.frame, **kw)
self.bind("
Using that is really easy. It wants to be loaded with an iterable, such as a list. So you could set it up like this:
So, there you have it — and I hope it saves you the enormous amount of time I spent trying to figure this stuff out. TkInter. You can actually use it now. If I find a way to pop up a TkInter treeview under Python 2.5.1 I’ll post about that, too. So far, no joy.import TkInter as tk
from scrolledlistclass import * # (that's the above list widget)
list = ['santa claus','paul bunyan','john doe','jane doe']
root=tk.Tk()
lb = ScrolledList(root, width=50, height=5, fg='black', pack=1)
lb.sets(list)
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
root.mainloop()
if (len(lb.sel) != 0):
sel = int(lb.sel[0]) # here's your selection, an index into the above list
sel = alist[sel]
else:
sel = -1
print str(sel)
#1 by George Griffin on August 10, 2011 - 3:41 pm
Quote
I have found that if you include
root.wm_attributes(“-topmost”, 1)
before root.mainloop(), it will launch the GUI in front of the term.
#2 by admin on August 11, 2011 - 1:34 am
Quote
I’ll have to try that — thanks!
#3 by Keith on November 26, 2011 - 1:33 am
Quote
Hi,
I discovered your site here following a post you made asking how to get rid of the “Python” menu appearing automatically when using Tkinter. I am now sitting with the same challenge. Did you ever solve that problem?
Also into Ham Radio over here and working on an app for the hobby.
73s
zs6tw
#4 by admin on November 26, 2011 - 1:59 am
Quote
ZS6TW de AA7AS:
No, sure didn’t — came to the conclusion that Tkinter was just too badly broken to do serious work and abandoned the whole thing… just learned objective c and went after the native apis (which are also broken in a few important ways… no general IPC mechanism, keystrokes can only go to the currently active app, some other stuff… quite disappointing, actually.) But at least the menus work, hi hi.
#5 by Mark on February 16, 2017 - 9:25 am
Quote
I had to make the Python app name lowercase to work with the following command.
os.system(”’/usr/bin/osascript -e ‘tell app “Finder” to set frontmost of process “python” to true’ ”’)
I am not sure why mine is lowercase when others have capitalized app names.
#6 by admin on February 16, 2017 - 9:31 am
Quote
If you’re using a Mac, have you set your filesystem to be case-sensitive? The Mac default is non-case-sensitive.