• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/pyobjc/pyobjc-core-2.5.1/Doc/sphinx_build/html/_sources/tutorials/
1=======================================
2Creating your first PyObjC application.
3=======================================
4
5WARNING: This tutorial assumes you're using Xcode 2.5 and is therefore not 
6entirely valid with Xcode 3 (that is MacOS 10.5).
7
8In this tutorial you will learn how to create your first Python Cocoa
9application: a simple dialog that allows you to convert amounts of money from
10one currency to another.  Definitely easier to do with a calculator, but in the
11process of following the tutorial you will learn which bits of Apple's Cocoa
12documentation apply to PyObjC and which bits are different, and how to adapt
13the different bits to PyObjC from Objective-C.
14
15To follow the tutorial you need:
16
17 * PyObjC 1.3.1
18 * py2app 0.2 or later (included in the binary installer for PyObjC)
19 * Python 2.3 or later (note: PyObjC is NOT compatible with MacPython-OS9)
20 * Mac OS X 10.2 or later
21 * Xcode Tools (was Developer Tools for Mac OS X 10.2)
22
23If you do not have a ``/Developer`` folder, then you do not have Xcode Tools
24installed.  See `Getting the Xcode Tools`_.
25
26.. _`Getting the Xcode Tools`: http://developer.apple.com/tools/download/
27
28Getting Started
29---------------
30
31.. note:: Before you start, download the :download:`reference source package <firstapp_src.zip>` for this tutorial.
32
331. Create a work directory ``src``.  Check which Python you have installed
34   PyObjC for, by running ``python`` and checking that ``import Foundation``
35   works.  If it does not work it could be that you have installed PyObjC for
36   ``/usr/local/bin/python`` but Apple's ``/usr/bin/python`` comes first in
37   your ``$PATH``.  Make sure you use the right python wherever it says
38   ``python`` in this tutorial.
39   
402. Start Interface Builder, select *Cocoa Application*
41   in the new file dialog, save this file as ``src/MainMenu.nib``.
42   
433. Proceed with the instructions as lined out in Apple's
44   `Developing Cocoa Objective-C Applications: a Tutorial`_, `chapter 3`_,
45   just after the section "*Creating the Currency Converter Interface*".
46   Work through "Defining the Classes of Currency Converter", "Connecting
47   ConverterController to the Interface", and stop at
48   "*Implementing the Classes of Currency Converter*", as we are going to do
49   this in Python, not Objective-C.  Your nib file should now be the same as
50   *step3-MainMenu.nib*.
51   
52.. _`Developing Cocoa Objective-C Applications: a Tutorial`: http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html
53.. _`chapter 3`: http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html?http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/chapter03/chapter_3_section_1.html
54
554. Create the skeleton Python script by running the ``nibclassbuilder`` script.
56   ``nibclassbuilder`` will parse the NIB file and create a skeleton module for
57   you.  Invoke it as follows (from the ``src`` directory):
58
59   .. sourcecode:: sh
60   
61       $ python -c "import PyObjCScripts.nibclassbuilder" MainMenu.nib > CurrencyConverter.py
62               
63   Depending on your installation, the ``nibclassbuilder`` script may be on your ``$PATH``.
64   If so, it can be invoked as such:
65
66   .. sourcecode:: sh
67
68       $ nibclassbuilder MainMenu.nib > CurrencyConverter.py
69   
70   The result of this can be seen in *step4-CurrencyConverter.py*.
71
72Testing the user interface
73--------------------------
74
755. Now we need to create an build script for CurrencyConverter.  To do this,
76   create a file named ``setup.py`` with the following contents:
77
78   .. sourcecode:: python
79      :linenos:
80   
81        from distutils.core import setup
82        import py2app
83
84        setup(
85            app=['CurrencyConverter.py'],
86            data_files=['MainMenu.nib'],
87        )
88
89   The result of this can be seen in *step5-setup.py*.
90
916. Run the setup script to create a temporary application bundle for
92   development:
93
94   .. sourcecode:: sh
95
96        $ python setup.py py2app -A
97      
98   Note that we use the ``-A`` argument to create an alias bundle at 
99   ``dist/CurrencyConverter.app``.  Alias bundles contain an alias to the
100   main script (``CurrencyConverter.py``) and symlinks to the data files
101   (``MainMenu.nib``), rather than including them and their dependencies
102   into a standalone application bundle.  This allows us to keep working on
103   the source files without having to rebuild the application.  This alias
104   bundle is similar to a ZeroLink executable for Xcode - it is for
105   DEVELOPMENT ONLY, and will not work on other machines.
106   
1077. Run the program.  This can be done in three ways:
108
109   - double-click ``dist/CurrencyConverter`` from the Finder
110     (you won't see the .app extension)
111
112   - open it from the terminal with:
113
114     .. sourcecode:: sh
115   
116        $ open dist/CurrencyConverter.app
117       
118   - run it directly from the Terminal, as:
119
120     .. sourcecode:: sh
121   
122        $ ./dist/CurrencyConverter.app/Contents/MacOS/CurrencyConverter
123       
124   The last method is typically the best to use for development: it leaves
125   stdout and stderr connected to your terminal session so you can see what
126   is going on if there are errors, and it allows you to interact with ``pdb``
127   if you are using it to debug your application.  Note that your application
128   will likely appear in the background, so you will have to cmd-tab or click
129   on its dock icon to see its user interface.
130   
131   The other methods cause stdout and stderr to go to the Console log, which
132   can be viewed with ``/Applications/Utilities/Console.app``.
133   
134   When you run your script as it is now it should behave identically as when
135   you tested your interface in Interface Builder in step 3, only now the
136   skeleton is in Python, not Objective-C.
137   
138
139Writing the code
140----------------
141
1428.  Time to actually write some code.  Open ``CurrencyConverter.py`` in your
143    favorite text editor.  Follow Apple's documentation again, chapter 3,
144    section "Implementing Currency Converter's Classes".  To translate this
145    Objective C code to Python syntax, we will need to do some name mangling of
146    the selectors.  See *An introduction to PyObjC* for the details, but the
147    short is that:
148
149    .. sourcecode:: objective-c
150
151        [anObject modifyArg: arg1 andAnother: arg2]
152
153   translates into the following Python code, by replacing the colons in the
154   selector with underscores, and passing the arguments as you would with a
155   normal Python method call:
156
157   .. sourcecode:: python
158
159        anObject.modifyArg_andAnother_(arg1, arg2)
160   
161   Note that we don't do this mangling for ``Converter.convertAmount()``: this
162   method is only called by other Python code, so there is no need to go
163   through the name mangling.  Also, if we would want to make this method
164   callable from ObjC code we may have to tell the PyObjC runtime system about
165   the types of the arguments, so it could do the conversion.  This is beyond
166   the scope of this first tutorial, *An introduction to PyObjC* has a little
167   more detail on this.
168   
169   The application should now be fully functional, try it.  The results of what
170   we have up to now can be seen in *step8-CurrencyConverter.py*.
171   
172Extending the functionality
173---------------------------
174
1759.  We are going to add one more goodie, just to show how you edit an existing
176    application.  The main problem, which may be obvious, is that we cannot run
177    ``nibclassbuilder`` again because we would destroy all the code we wrote in
178    steps 5 and 8, so we do this by hand.  What we are going to do is add an
179    "invert rate" command, because I always get this wrong: instead of typing
180    in the exchange rate from dollars to euros I type in the rate to convert
181    from euros to dollars.
182   
183    Open ``MainMenu.nib`` in Interface Builder.  Select the *Classes* view and
184    then select the ``ConverterController`` class.  In the info panel select
185    the *Attributes* from the popup.  Select the *Actions* tab, and add an
186    action ``invertRate:``.  You have now told Interface Builder that instances
187    of the ``ConverterController`` class have grown a new method
188    ``invertRate_()``.
189   
190    In the ``MainMenu.nib main`` window open the *MainMenu* menubar.  Select
191    the ``Edit`` menu.  Make sure the *Menus* palette is open and selected,
192    drag a separator to the ``Edit`` menu and then drag an ``Item`` there.
193    Double-click the item and set the text to ``Invert Exchange Rate``.
194   
195    Make the connection by control-dragging from the new
196    ``Invert Exchange Rate`` menu item to the ``ConverterController`` instance
197    in the Instances tab in the ``MainMenu.nib`` main window.
198
199    *NOTE:* you drag to the *instance* of ``ConverterController``, not to the
200    class.
201
202    In the *Info* panel, *Connections* section, select ``invertRate:`` and
203    press *Connect*. 
204   
20510. We know our program can't invert rates yet, because we haven't actually
206    written the code to do it, but we are going to try it anyway, just to see
207    what sort of spectacular crash we get.  Alas, nothing spectacular about it:
208    when the NIB is loaded the Cocoa runtime system tries to make the
209    connection, notices that we have no ``invertRate_()`` method in our
210    ``ConverterController`` class and it gives an error message:
211
212    .. sourcecode:: sh
213       
214       $ ./dist/CurrencyConverter.app/Contents/MacOS/CurrencyConverter 
215       2004-12-09 03:29:09.957 CurrencyConverter[4454] Could not connect the action 
216       invertRate: to target of class ConverterController
217   
218    Moreover, it has disabled the ``Invert Exchange Rate`` menu command and
219    continues, so the program works as it did before, only with one more
220    (disabled) menu item.
221   
222Debugging
223---------
224
22511. Writing the code is easy: add a method ``invertRate_(self, sender)`` that
226    gets the float value of ``rateField``, inverts it and puts it back.  We
227    deliberately forget to test for divide by zero.  We run the program again,
228    and now the menu entry is enabled.  After trying it with a couple of
229    non-zero exchange rates we try it with an exchange rate of zero (or empty,
230    which is the same).  We get a dialog box giving the Python exception, and
231    offering the choice of continuing or quitting. 
232    
233    To debug this application with pdb, start the application with the
234    following command line:
235
236    .. sourcecode:: sh
237
238        $ env USE_PDB=1 ./dist/CurrencyConverter.app/Contents/MacOS/CurrencyConverter
239
240    When running in this mode, we will get a ``pdb.post_mortem(...)`` console
241    in the terminal instead of the alert panel.  You can see this in action if
242    you try and invert an exchange rate of ``0``.
243      
24412. Fix the final bug by testing for ``rate == 0.0`` in ``invertRate_()``.
245    The result is in the *step12-src* directory.
246   
247Creating a redistributable application
248--------------------------------------
249
250Your application is finished, and you want to run it on other computers, or
251simply just move it to the ``Applications`` folder (or anywhere else) and
252insulate it from the original source code.
253
254This can be done with the following steps from the ``src`` directory:
255
256 .. sourcecode: sh
257
258    $ rm -rf dist
259    $ python setup.py py2app
260
261Now the application bundle located at ``dist/CurrencyConverter.app`` is a fully
262standalone application that should run on any computer running the same major
263version of Mac OS X or later.  This means that applications built on
264Mac OS X 10.2 are compatible with Mac OS X 10.3, but NOT vice versa.  If you
265are not using an Apple-supplied version of Python, a subset of your Python
266installation will be included in this application.
267
268For more complicated examples of py2app usage to do things such as change the
269application's icon, see the Examples or the py2app documentation.
270