Recipe 11.18. Building a Python Cocoa GUI Programmatically
Credit: Dethe Elza
Problem
You are developing a Python application using Mac OS
X's Aqua interface (through Apple's
Cocoa toolkit and the PyObjC, Python/Objective-C bridge). You want to
build the application's user interface within the
program itself (as is normally done in most other Python GUI
toolkits), rather than via Apple's Interface Builder
(IB) and resulting .nib files (as is usually
done with Cocoa for Aqua applications).
Solution
Anything that you can do via Interface Builder and
.nib files, you can also do directly in your
program. Here is a simple demo:
from math import sin, cos, pi
from Foundation import *
from AppKit import *
class DemoView(NSView):
n = 10
def X(self, t):
return (sin(t) + 1) * self.width * 0.5
def Y(self, t):
return (cos(t) + 1) * self.height * 0.5
def drawRect_(self, rect):
self.width = self.bounds( )[1][0]
self.height = self.bounds( )[1][1]
NSColor.whiteColor( ).set( )
NSRectFill(self.bounds( ))
NSColor.blackColor( ).set( )
step = 2 * pi/self.n
loop = [i * step for i in range(self.n)]
for f in loop:
p1 = NSMakePoint(self.X(f), self.Y(f))
for g in loop:
p2 = NSMakePoint(self.X(g), self.Y(g))
NSBezierPath.strokeLineFromPoint_toPoint_(p1, p2)
class AppDelegate(NSObject):
def windowWillClose_(self, notification):
app.terminate_(self)
def main( ):
global app
app = NSApplication.sharedApplication( )
graphicsRect = NSMakeRect(100.0, 350.0, 450.0, 400.0)
myWindow = NSWindow.alloc( ).
initWithContentRect_styleMask_backing_defer_(
graphicsRect,
NSTitledWindowMask
| NSClosableWindowMask
| NSResizableWindowMask
| NSMiniaturizableWindowMask,
NSBackingStoreBuffered,
False)
myWindow.setTitle_('Tiny Application Window')
myView = DemoView.alloc( ).initWithFrame_(graphicsRect)
myWindow.setContentView_(myView)
myDelegate = AppDelegate.alloc( ).init( )
myWindow.setDelegate_(myDelegate)
myWindow.display( )
myWindow.orderFrontRegardless( )
app.run( )
print 'Done'
if _ _name_ _ == '_ _main_ _':
main( )
Discussion
Most programmers prefer to lay out their programs'
user interfaces graphically, and Apple's Interface
Builder application, which comes with Apple's free
Developer Tools (also known as XCode), is a particularly nice tool
for this task (when you're using
Apple's Cocoa toolkit to develop a GUI for Mac OS
X's Aqua interface). (The PyObjC extension makes
using Cocoa from Python an obvious choice, if you're
developing applications for the Macintosh.)Sometimes it is more convenient to keep all the GUI building within
the very program I'm developing, at least at first.
During the early iterations of developing a new program, I often need
to refactor everything drastically as I rethink the problem space.
When that happens, trying to find all the connections that have to be
modified or renamed is a chore in Interface Builder or in any other
such interactive GUI-painting application.Some popular GUI toolkits, such as Tkinter, are based on the idea
that the program builds its own GUI at startup by defining the needed
objects and appropriately calling functions and methods. It may not
be entirely clear to users of other toolkits, such as Cocoa, that
just about every toolkit is capable of operating in a similar manner,
allowing "programmatic" GUI
construction. This applies even to those toolkits that are most often
used by means of interactive GUI-painting applications. By delaying
the use of IB until your program is more functional and stable,
it's more likely that you'll be
able to design an appropriate interface. This recipe can help get you
started in that direction.This recipe's code is a straight port of
tiny.m, from Simson Garfinkel and Michael
Mahoney, Building Cocoa Applications: A Step-by-Step
Guide (O'Reilly), showing how to build a
Cocoa application without using Interface Builder nor loading
.nib files. This recipe was my first PyObjC
project, and it is indebted both to the Cocoa book and to
PyObjC's "Hello
World" example code. Starting from this simple,
almost toy-level recipe, I was able to use Python's
file handling to easily build a graphical quote viewer and ramp up
from there to building rich, full-fledged GUIs.
See Also
Garfinkel and Mahoney's Building Cocoa
Applications: A Step-by-Step Guide
(O'Reilly); PyObjC is at http://pyobjc.sourceforge.net/.