1<HTML><HEAD><TITLE>Using python to create Macintosh applications, part two</TITLE></HEAD> 2<BODY> 3<H1>Using python to create Macintosh applications, part two</H1> 4<HR> 5 6In this document we rewrite the application of the <A 7HREF="example1.html">previous example</A> to use modeless dialogs. We 8will use an application framework, and we will have a look at creating 9applets, standalone applications written in Python. The <A 10HREF="example2/dnslookup-2.py">source code</A> and 11<A HREF="example2/dnslookup-2.rsrc">resource file</A> are available in the folder 12<A HREF="example2">example2</A>. <p> 13 14Again, we start with ResEdit to create our dialogs. Not only do we 15want a main dialog this time but also an "About" dialog. This example is less 16than complete since we do not provide a <A NAME="bundle">BNDL resource</A> 17and related stuff that an application cannot be without. We are able to do this 18when building a python applet since BuildApplet will substitute default resources 19for BNDL, etc. when none are supplied (<A HREF="#no-bundle">See below</A>.) 20"Inside Mac" or various 21books on Macintosh programming will help here. Also, you can refer to 22the resource files provided in the Python source distribution for some 23of the python-specific points of BNDL programming: the 24"appletbundle.rsrc" file is what is used for creating applets if you 25don't provide your own resource file. <p> 26 27When creating your own BNDL resouorces, keep in mind that the Finder gets 28confused if you have more than one application with the same signature. This may be due 29to some incorrectness on the side of "BuildApplet", I am not sure. There is one 30case when you definitely need a unique signature: when you create an applet that 31has its own data files and you want the user to be able to start your 32applet by double-clicking one of the datafiles. <p> 33 34Let's have a look at dnslookup-2.rsrc, our resource file. Dialog 512 is the 35main window which has one button (Lookup), two labels and 36two text entry areas, one of which is used for output only. The "Quit" 37button has disappeared, because its function is handled by a menu choice. Here's 38what it will look like at run time:<p> 39<div align=center> 40<img width=324 height=205 src="example2/dnslookup-2.gif" alt="dialog image"> 41</div> 42<p> 43 44<H2>A modeless dialog application using FrameWork</H2> 45 46On to the source code in <A 47HREF="example2/dnslookup-2.py">dnslookup-2.py</A>. The 48start is similar to our previous example program <A 49HREF="example1/dnslookup-1.py">dnslookup-1.py</A>, with 50one extra module being imported. To make life more simple we will use 51the <CODE>FrameWork</CODE> module, a nifty piece of code that handles 52all the gory Mac details of event loop programming, menubar 53installation and all the other code that is the same for every Mac 54program in the world. Like most standard modules, FrameWork will run 55some sample test code when you invoke it as a main program, so try it 56now. It will create a menu bar with an Apple menu with the about box 57and a "File" menu with some pythonesque choices (which do nothing 58interesting, by the way) and a "Quit" command that works. <p> 59 60<BLOCKQUOTE> 61If you have not used <code>FrameWork</code> before you may want to 62first take a look at the <A HREF="textedit.html">Pathetic EDitor</A> 63example, which builds a minimal text editor using FrameWork and TextEdit. 64On the other hand: we don't use many features of FrameWork, so you could 65also continue with this document. 66</BLOCKQUOTE> 67 68After the imports we get the definitions of resource-IDs in our 69resource file, slightly changed from the previous version of our 70program. The main program is also 71similar to our previous version, with one important exception: we 72first check to see whether our resource is available before opening 73the resource file. Why is this? Because later, when we will have 74converted the script to an applet, our resources will be available in 75the applet file and we don't need the separate resource file 76anymore. <p> 77 78Next comes the definition of our main class, 79<CODE>DNSLookup</CODE>, which inherits 80<CODE>FrameWork.Application</CODE>. The Application class handles the 81menu bar and the main event loop and event dispatching. In the 82<CODE>__init__</CODE> routine we first let the base class initialize 83itself, then we create our modeless dialog and finally we jump into 84the main loop. The main loop continues until we call <CODE>self._quit</CODE>, 85which we will do when the user selects "Quit". When we create 86the instance of <CODE>MyDialog</CODE> (which inherits 87<CODE>DialogWindow</CODE>, which inherits <CODE>Window</CODE>) we pass 88a reference to the application object, this reference is used to tell 89Application about our new window. This enables the event loop to keep 90track of all windows and dispatch things like update events and mouse 91clicks. <p> 92 93The <CODE>makeusermenus()</CODE> method (which is called sometime 94during the Application <CODE>__init__</CODE> routine) creates a File 95menu with a Quit command (shortcut command-Q), which will callback to 96our quit() method. <CODE>Quit()</CODE>, in turn, calls <CODE>_quit</CODE> which 97causes the mainloop to terminate at a convenient time. <p> 98 99Application provides a standard about box, but we override this by 100providing our own <CODE>do_about()</CODE> method which shows an about 101box from a resource as a modal dialog. This piece of code should look 102familiar to you from the previous example program. That do_about is 103called when the user selects About from the Apple menu is, again, 104taken care of by the __init__ routine of Application. <p> 105 106The <CODE>MyDialog</CODE> class is the container for our main 107window. Initialization is again done by first calling the base class 108<CODE>__init__</CODE> function and finally setting the local variable 109"parent." <p> 110 111<CODE>Do_itemhit()</CODE> is called when an item is selected in this 112dialog by the user. We are passed the item number (and the original 113event structure, which we normally ignore). The code is similar to the 114main loop of our previous example program: a switch depending on the 115item selected. <CODE>Dnslookup()</CODE> is quite similar to our previous 116example. <p> 117 118<H2><IMG SRC="html.icons/mkapplet.gif"><A NAME="applets">Creating applets</A></H2> 119 120Now let us try to turn the python script into an applet, a standalone 121application. This will <em>not</em> work if you have the "classic 68k" 122Python distribution, only if you have the cfm68k or PPC distribution. 123 124<blockquote> 125Actually, "standalone" is probably not the correct term here, since an 126applet does still depend on a lot of the python environment: the 127PythonCore shared library, the Python Preferences file, the python Lib 128folder and any other modules that the main module depends on. It is 129possible to get rid of all these dependencies and create true standalone 130applications in Python, but this is a bit difficult. See <a href="freezing.html"> 131Standalone Applications in Python</a> for details. For this 132document, by standalone we mean here that 133the script has the look-and-feel of an application, including the 134ability to have its own document types, be droppable, etc. 135</blockquote> 136 137The easiest way to create an applet is to take your source file and 138drop it onto "BuildApplet", located in the Python home 139folder. This will create an applet with the same name as your python 140source with the ".py" stripped. Also, if a resource file with the same 141name as your source but with ".rsrc" extension is available the 142resources from that file will be copied to your applet too. If there 143is no resource file for your script a set of default resources will be 144used, and the applet will have the default creator 'Pyt0'. The latter 145also happens if you do have a resource file but without the BNDL 146combo. <A NAME="no-bundle">Actually</A>, as in the present example. 147<p> 148 149If you need slightly more control over the BuildApplet process you can 150double-click it, and you will get dialogs for source and 151destination of the applet. The rest of the process, including locating 152the resource file, remains the same. <p> 153 154Note that though our example application completely bypasses the 155normal python user interface this is by no means necessary. Any python 156script can be turned into an applet, and all the usual features of the 157interpreter still work. <p> 158 159That's all for this example, you may now return to the <A HREF="index.html"> 160table of contents</A> to pick another topic. <p> 161</BODY> 162</HTML> 163