Very Simple OS X Cocoa Application using Python and Interface Builder

SimpleXibDemo

The Very Simple App

I’ve been playing around with creating a small Cocoa App for the last week or so. Finding good examples and documentation has been a little problematic, so I’ve put together a tiny application as a reference point to get going when starting fresh. It’s built entirely in Python using Cocoa through the PyObjC wrappers. It includes a XIB created with Interface Builder in Xcode. Bundling the App for distribution is a snap using the py2app command in setuptools.

Source on GitHub: simple_pyobjc_cocoa_xib

All the required Python:

The most useful resource for me has been the source available in the PyObjC examples. One thing that took a while to figure out was how the initial NIB and window are loaded when some of the examples start. The Info.plist file generated by py2app includes the NSMainNibFile element which instructs OS X to load the MainMenu NIB when launching by default.

The py2app tutorial has been useful for getting the initial project set up.

Below are the steps I took to create the application with a 5 minute video of the process at the bottom.

Create setup.py

The tool used to create a setup.py file is py2applet. It is not in the PATH by default so the full path can be used to run it.

 $ /System/Library/Frameworks/Python.framework/Versions/Current/Extras/bin/py2applet --make-setup SimpleXibDemo.py

By default, the setup.py created by py2applet has argv_emulation set to True. This flag enables dragging of files onto our application in OS X. It’s not supported with the latest libraries, and this application that functionality. So it can be removed from the OPTIONS dict.

To include the XIB that will be created later in the application, it’s added to the DATA_FILES list.

DATA_FILES = ['SimpleXibDemo.xib']

The Python Source

The Python source for the application is all in one file, SimpleXibDemo.py. It consists of one class (SimpleXibDemoControllerand a __main__ block to get the application up and running.

Inheriting from the NSWindowController class gives the SimpleXibDemoController class the responsibility of managing a window. It handles events like windowDidLoad to get hooks into the windows lifecycle.

The local variable counterTextField is initialized to objc.IBOutlet(). This allows in Interface builder to assign a reference to a Label to it for providing output to the user.

The @objc.IBAction decorators on a couple functions expose them to Interface Builder as so the functions can be called when a Push Button is activated.

Creating a XIB in Interface Builder

In Xcode, click File… New… File… Create and OS X User Interface Window. Save it with the file name that was referenced above in the setup.py; SimpleXibDemo.xib.

Drag three Push Button elements and one Label element into the new window. The buttons text can be changed by double clicking on them.

Window XIB Drag Buttons

Add the SimpleXibDemo.py file to Xcode in File… Add Files… Interface Builder will recognize the Python file and find the objc.IBOutlet() and @objc.IBAction elements.

Click on File’s Owner in the left pane with the projects objects and choose the identity inspector tab in the top right. Change the Class value to our Python class SimpleXibDemoController. 

Files Owner Class

Set the “File’s Owner” class

 

Attaching the IBOutlet and IBActions in Interface Builder:

Interface Builder dragging Actions Outlets

Hold down CTRL and drag from File’s Owner to the Label. Select the counterTextField outlet.

Hold down CTRL and drag from the decrement button to the File’s Owner. Select the decrement: action. Do the same for the increment button, but select the increment: action.

Hold down CTRL and drag fro the Quit button to the Application object and chose the terminate: action.

Run in Alias Mode for Development

While working on the App, it’s convenient to build it in Alias mode. Resources in the build are aliased to source code, so changes can be previewed without going through a whole rebuild.

$ python setup.py py2app -A

Run the application in Aliased mode:

$ dist/SimpleXibDemo.app/Contents/MacOS/SimpleXibDemo

Build for Distribution

The application is built for distribution using the same py2app command, but without the Alias flag.

$ python setup.py py2app

The distributable Application can be found in the dist folder.

Video of the workflow

 

2 thoughts on “Very Simple OS X Cocoa Application using Python and Interface Builder

  1. Michal Dobrzynski

    Hi,

    I found your example very useful and it allowed me to begin prototyping a small application that I hope will make my parents life easier, hover, I have not been able to figure out how I might go about adding a TableView inside.

    The only thing I found was this:
    http://pythonhosted.org/pyobjc/examples/Cocoa/AppKit/TableModel/

    and I could not figure out how in the world I could combine your example with this so that I could have both in the same window.

    I’d love to see more tutorials of this type as what you have done already has been VERY helpful to me :)

    Regards,
    Michal

  2. adamw523 Post author

    I haven’t done anything in Cocoa yet with tabular data, but I have been scraping some code off one example that does set up a Model provider for a table. It seems interesting and might of help:

    http://pythonhosted.org/pyobjc/examples/Cocoa/AppKit/PythonBrowser/index.html

    It’s been really helpful for me to actually download the example projects and open up the NIBs in Interface Builder to see what they’ve done with connecting the outlets and actions.

    Best of luck!

Leave a Reply