Mac-optimized wx apps

Macs are experiencing extensive growth these days, and the Mac App Store is clearly a great tool for software developers who wish to sell their software to the world. So more than ever, it’s important that whatever tool you use to create Mac software can make a “good Mac citizen.”

So is wx, specifically wxPython, up to the task? This series of blog entries will attempt to chronicle my attempts to find out.

Let’s start with first things first. The “no window” app. On Mac, an app can have no windows open, but have a menubar, so you can say, create a document. Some start that way, although most don’t. ┬áCan wx handle this? Let’s test the 2.9.1.1 OS X Cocoa build and find out.

The answer is, sort of. You can create an app that has an app-level menu bar and set the wx.App to handle events on it, and by calling SetExitsOnFrameDelete(False) on the app, you can keep the app alive even if all top level frames are closed / destroyed. However, what you can’t do is NOT create a frame when initializing the app. Even if SetExitsOnFrameDelete(False) is called, if during initialization there is no frame, the app will still shut down. Here is some sample code that exhibits this:
[code]
import wx
NewFrameAction = wx.NewId()

class MyAppDelegate:
def RegisterEvents(self):
self.Bind(wx.EVT_MENU, self.OnNewFrame, id=NewFrameAction)

def OnNewFrame(self, event):
self.NewFrame()

def NewFrame(self):
frame = wx.Frame(None, -1, “Test Frame”)
frame.CentreOnScreen()
frame.Show()

class MyApp(wx.PySimpleApp, MyAppDelegate):
def OnInit(self):
self.SetExitOnFrameDelete(False)
file_menu = wx.Menu()
file_menu.Append(NewFrameAction, “New Frame”)

menu_bar = wx.MenuBar()
menu_bar.Append(file_menu, “File”)

wx.MenuBar.MacSetCommonMenuBar(menu_bar)
self.NewFrame()
self.RegisterEvents()
return True

app = MyApp()
app.MainLoop()
[/code]

If you remove the self.NewFrame() call from OnInit, the app will simply exit. However, in most cases, you do want to initialize some frame when the app starts, so this is not really a show-stopper, though it would be nice if this could be fixed somehow. Also, one other thing, going into the Python menubar and hitting “Quit” does not quit the app, although doing it from the Dock works. This is probably due to the Python.app bundle not handling Quit properly, and is fixed if you build and run MyApp.app using py2app, but this is a confusing quirk that will probably look like a bug. It would be nice if wxPython eventually had a “sample app” with a “run” script that would build the script into an app using py2app and run it that way.
Next up, I’ll take a look at wx.dataview.DataViewCtrl and see how well it does at giving us a nice, native looking list/tree control.