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