Creating a Complete PythonCard Application from Scratch
Background
This is the second in a series of PythonCard walk-through documents. It
assumes you have either read and worked your way through
PythonCard Walk-Through No. 1
which teaches you the basics of working in the PythonCard environment
or that you already understand those basics.
Purpose and Scope
The purpose of this walk-through is to walk you, step by step, through
the process of creating a PythonCard application. By the time you
have finished this walk-through, you will:
- understand how PythonCard's GUI building facilities work
- know how to create a starting point for a new PythonCard application
- have a grasp of the basic event-handling architecture that gives PythonCard
applications life
- know how to create menus and menu items in PythonCard and to hook
those items up to actions
Over the years as I've played with various GUI tools and development environments,
I have traditionally created a simple counter application as a way
of getting familiar with the tool's basic operation and gaining some
nodding acquaintance with its language and architecture/API. When PythonCard
appeared in my life courtesy of my old colleague Kevin Altis, I decided
that I should do the same. Kevin encouraged me to document my efforts
and this is the result.
This document walks you step by step through the process of creating
an intentionally simplistic PythonCard application. I don't claim that
this is the best way to accomplish this objective, let alone the only
one. It just happens to be the way I approached it. At the end of this
tutorial, I will make a few observations about other things that I could
have done that would make the example more instructive or interesting.
Note that this tutorial describes how this process is handled in PythonCardPrototype
0.6.4. Continuing enhancements to the UI, especially in the resourceEditor,
will make the process more and more streamlined over time.
The Application
This simple application, the finished result of which is shown in Figure
1, consists of three buttons and a text field. The text field holds
a numeric value (represented as a string) which is manipulated by the
three buttons. The buttons add 1 to the current value displayed in
the field, subtract 1 from that field's value, and reset the field's
value to 0.
Figure 1. Finished Counter Walk-Through Application
The Application Creation Process
Creating an application in PythonCard begins with the creation of a basic
structure. There are two ways to do this. One is to use the PythonCard
Resource Editor (called resourceEditor.py), start with the basic
empty window, and code from scratch. The other is to copy an existing
application's folder, rename a few basic things, and begin with a
somewhat more complete starting point. I'm taking the latter course
here.
The process in summary
- Run resourceEditor to create or modify an existing application.
- Lay out the application's window in Resource Editor.
- Script the components that will trigger actions (buttons and/or
menus)
- Cleaning up artifacts of the copied program. Let's go through those
steps with my simple Counter tutorial.
A. Run resourceEditor to modify an existing application.
- Make a copy of the "minimal" project folder in the samples folder
of the PythonCard distribution. Put into its own folder called "counter."
(The folder name isn't important to PythonCard.)
- Rename "minimal.py" to "counter.py" and "minimal.rsrc.py" to "counter.rsrc.py."
- Launch resourceEditor, which is found in the PythonCard distribution's
tools folder
- Open the file counter.rsrc.py in the folder you just created.
The window looks identical to the minimal application when it is running,
except for the menu bar which remains the resourceEditor's menu bar
(since we are running resourceEditor at the moment) rather than the Counter
application's menu bar. Figure 2 depicts this start-up situation. resourceEditor
is a "live" editor; the application is running while you edit it.
Figure 2. Startup Screen for Walk-Through Counter Application
B. Laying out the window for the counter tutorial application.
- Select the text field containing the words "Hello PythonCard" by
clicking anywhere in it.
- In the Property Editor window, select the "text" property in the right-hand
list of properties for the field1 Text Field object. Select the words
in the field and delete them with the Backspace key.
- Type the number "42" (or some other number; I just happen to be a
Douglas Adams fan) into the box.
- Click Update.
- In the Property Editor window, select the "font" property in the right-hand
list of properties for the field1 Text Field object. Click on the "Font"
button and set the font size to 24. [Note that there is a bug in the GTK
version of wxPython 2.3.2.1 that prevents the font from being changed. This
will be fixed in the next release of wxPython.]
- Click Update.
- Use the resize handles to shape the field so that the entire value
"42" shows. Then position the field near the right edge of the window
and approximately centered vertically. (You will probably need to resize
the window itself; use the same technique for doing so on your system
as you'd use for any window.)
- Select the "editable" property of the Text Field object called field1
and uncheck the checkbox. (By making the field read-only, we avoid
the necessity of error-checking that would be required if we let the
user enter a value directly into the field.)
- Click Update.
- Select Save from the File menu to save the counter.rsrc.py resource
file.
- From the "Components" menu, select "Add Button"
- In the Property Editor window, select the "name" property in the right-hand
list of properties for the Button1 Button object. Change the default name
to 'incrBtn' (for "increment button")
- Click Update.
- In the Property Editor window, select the "label" property in the
right-hand list of properties for the incrBtn Button object. Change the
label from 'Button1' to 'Increment'.
- Click Update.
- Position this button in the upper left portion of the window.
- Repeat steps 11-15, but this time change the default 'name' to 'decrBtn'
(for "decrement button") and the 'label' from 'Button1' to 'Decrement'.
Remember to click the "Update" button in the Property Editor after setting
each property.
- Position the Decrement button below the Increment button, approximately
in the middle of the window.
- Repeat steps 11-15 one more time. Change the default 'name' to 'resetBtn'
and the 'label' to 'Reset'.
- Position the Reset button to the bottom of the vertical row of three
buttons.
- Save your work.
Your project should now look like Figure 3.
Figure 3. Project With Buttons Added
C. Scripting the Buttons
Application scripts are stored in the Python (.py) file that represents
the application. In this case, that means they are in the file counter.py.
- Using PythonCard's built-in codeEditor or your favorite Python code
editor, open the file counter.py. It is a small file with a self-explanatory
comment and only one event-handling script right now (which responds to
the user selecting Exit from the File menu). codeEditor is found in the
tools directory of your PythonCard distribution.
- Position your cursor below the last line of the
on_menuFileExit_select(self,
event):
handler.
- Enter the following script, remembering that Python is white-space-aware
so that indentations of lines are significant.
def on_incrBtn_mouseClick(self, event):
startValue = int(self.components.field1.text)
endValue = startValue +
1
self.components.field1.text
= str(endValue)
Let's examine this script because the others we will write are all
but identical.
The opening line of a PythonCard event handler always starts
with the keyword "def" which is standard Python for function and method
definition. The next expression in the line starts with the PythonCard
keyword "on_" and is followed by the name of the component we are scripting.
In this case, it's the Increment Button, whose name is "incrBtn." After
another connecting underscore, the last portion of the handler definition
line defines the event for which this handler is to be called. All events
take the same basic set of parameters as shown above.
The next lines are simple Python for the most part. The first line defines
a variable called "startValue" to which we assign the current contents
of the field, coerced to an integer so we can perform arithmetic on it.
The second line adds one to the value we just retrieved. The third line
assigns this new result to the field's text property after coercing it to
a string.
- As long as we're in the application's main code file, let's also make
our program a little more internally consistent. Change the name of the
class we're creating from Minimal to Counter. At the end of the file,
replace "Minimal" with "Counter" in the line that begins "app = ". The
result should look like Figure 4.
Figure 4. Code Changes in counter.py
- Save your work.
- From the resourceEditor's File menu, select "Run."
- When the Counter application appears, click on the Increment button
and watch the displayed value in the text field to confirm that it is
incrementing as expected.
- Exit the application.
- Back in your Python Editor, copy the function we just created for the
Increment button and paste it under that function, being sure indentation
remains correct.
- Edit the new handler to change the name of the button from incrBtn
to decrBtn and the '+' sign to a minus (' - ') sign.
- Create a final handler for the Reset button that looks like this:
def on_resetBtn_mouseClick(self, event):
self.components.field1.text
= "0"
Figure 5 shows you what your editor window should look like now.
Figure 5. Editor Showing Final Code Changes
- Save your work and test the application again to be sure it still works.
What if the application doesn't run? In that case, you can use the
"Run with interpreter" command under the "File" menu to get a look at
what errors, if any, are occurring. To see this in action, let's introduce
a typographical error into counter.py. (You can skip this discussion
if you either already know how to do this or are confident that you'll
never create a PythonCard bug that will cause the programs to fail.)
- Open counter.py in your Python editor if it isn't already open.
- Change the word "class" to "classy" and save the program.
- Run the application as you have been doing. You will probably see
a brief console window appear and then disappear. Nothing else happens.
- From the File menu in resourceEditor, choose "Run With Interpreter."
This launches your PythonCard application with the Python interpreter
in a command console for your system so that you can see what error is
being generated.
- You should see a syntax error indicated in the new window. It should
be displaying the line where we created the intentional typo. (See Figure
6)
Figure 6. Error Shown in Console Window
- Press Ctrl-Z and Enter to terminate the Python interpreter and close
the console window.
- Go back to the counter.py file and fix the line. Save the file and
then re-run the application either from the resourceEditor's File menu
or from the command line.
D. Cleaning up artifacts of the original program
We already took care of changing the class name and the runtime invocation
name of the application from Minimal to Counter. Now let's change the
resource file to reflect the program's new name.
In resourceEditor, go to the Edit menu and select "Background Info..."
Change the name of the application to "PythonCard Counter" and click
OK.
That ends the basic aspect of this second PythonCard walk-through.
You now have a finished and working PythonCard application.
Optional Step: Adding a Menu
We'll add one optional step for a program like Counter, one which
you may well need to take in any application of even a little greater complexity
than this one. We'll add a menu to the application.
- In the resourceEditor, go to the Edit menu and choose "Menu Editor..."
- A dialog box appears (see Figure 7) with the current menu structure
displayed on the left. As you can see, the Counter application, which
was started from the sample application called minimal., has a single
menu with a single menu choice.
Figure 7. Opening Screen of Menu Editor
- Click on the "New Menu" button. You should see a dialog box like the
one in Figure 8.
Figure 8. New Menu Item Dialog Box
- In the editing area to the right of the display showing the menu,
change the name of the menu to menuCounterMenu and its label to Counter.
- Now click on "New Menu Item" and add a new menu item named "counterMenuIncrement."
Make its label "Increment."
- Click on "New Menu Item" again and do the same for new menu items "Decrement"
and "Reset." When you're done your work should look something like Figure
9.
Figure 9. Menu Editor With All Menu Items Defined
- Save your application in resourceEditor.
- Open the counter.py Python code file in your Python editor. Add the
handler name shown here:
def on_counterMenuIncrement_select(self, event):
- Copy the three lines of the function in
on_incrBtn_mouseClick
and paste them into the definition of this menu function. (Be sure
levels of indentation are consistent.)
- Follow the same procedure for hooking up the Decrement and Reset menu
options. When you're finished, your code window should look something
like Figure 10.
Figure 10. All Menu Items Programmed and Ready to Go
- Save your work.
(You'll notice that the new menu doesn't appear in your application
in resourceEditor. Rest assured it will be there when you run the application
outside resourceEditor.)
- Run the application (see Figure 11) and confirm everything works as
expected.
Figure 11. Finished Counter Application With Counter Menu
(NOTE that it would obviously be better design to factor out
the duplicated code into methods that handle the increment, decrement and
reset buttons and menus as processes and then to call those methods from
within the event handlers. We leave that you as an exercise for the reader.
Don't you hate when we do that to you?)
$Revision: 1.9 $, documentation updated on
$Date: 2002/06/29 08:03:37 $