Freshman Honors Seminar

CS U231 Fall 2006 and CS U232 Spring 2007

http://www.ccs.neu.edu/jpt/fhs/

This site will contain materials from both semesters of the freshman honors seminar CS U231 and CS U232 in 2006-2007.

Materials from previous years are at:

Links

Introductory Links

Applets 2006-2007

Exercises

Exercise 1

9/19/06

9/19/06: Introductory JPT Sampler

9/19/06: Class Foo: A miniature Java tutorial

9/19/06: Sum Panel Variations

9/19/06: Playing Cards

9/19/06: Sample Fonts

9/19/06: Visual Color List

9/19/06: Functions and Plots

9/19/06: Class KeyLabelData

9/20/06

9/20/06: Class Tic Tac Toe

9/21/06

9/21/06: Fibonacci Variations

9/26/06

9/26/06: Ball Animation

10/4/06

10/4/06: Table of Factorials

10/5/06

10/5/06: Classic Shapes

10/12/06

10/12/06: GeneralPath Shapes

10/23/06

10/23/06: Curve Mathematics

10/26/06

10/26/06: Polygons and Cubic Curves

11/13/06

11/13/06: Concentration Game

11/17/06

11/17/06: Random Shape Demos

11/17/06: Dice in Java and Scheme

11/20/06

11/20/06: Spinning Animation

12/1/06: Additional Applets

Links to earlier applets posted during Fall 2006

3/2/07

3/2/07: Functions Plotter

3/25/07

3/25/07: JPT Image IO

4/1/07

4/1/07: Keys, Animation, Threads

4/1/07

4/1/07: Counter Animation

4/5/07

4/5/07: Stack Trace, String Viewer, Bad GUI Applets

4/12/07

4/12/07: Ball Animation with SimpleThreadedAction

4/12/07: Ship: Graphics Composite

5/2/07: LayeredComponent

Introductory Links

The plan or syllabus for the Freshman Honors Seminar in Computer & Information Science as a Word document or PDF document.

Access to the Sun Java site

Sun Java Downloads

Access to the Eclipse site

Eclipse Downloads

Access to Eclipse 3.2 for Windows (one version back)

eclipse-SDK-3.2-win32.zip

Access to the Java Power Tools.

The main JPT site: http://www.ccs.neu.edu/jpt/

The JPT 2.5.0 site: http://www.ccs.neu.edu/jpt/jpt_2_5/

The JPT 2.5.0 library file jpt.jar: http://www.ccs.neu.edu/jpt/jpt_2_5/lib/jpt.jar

The JPT 2.5.0 javadocs: http://www.ccs.neu.edu/jpt/jpt_2_5/docs/

The JPT 2.5.0 annotated source code: http://www.ccs.neu.edu/jpt/jpt_2_5/src/

The Methods.java file that may be used as a template for the Java Power Framework.

The main cascading style sheet for this web site: fhs.css.

The screen cascading style sheet for this web site: fhs_screen.css.

Back to the Top

Down to the Bottom

9/19/06: Introductory JPT Sampler

The introductory JPT sampler is a class Methods.java that uses the Java Power Framework to create a test program that will execute 3 simple methods.

The first method named WriteHello utilizes the JPT console object to write the world “Hello” into the JPT console window.

The second method named SumOfInt contains the code to sum the integers from 1 up to a limit. This code is:

    public int SumOfInt(int limit) {
        int sum = 0;
        
        for (int n = 1; n <= limit; n++)
            sum += n;
        
        return sum;
    }

This is a very simple Java method that accepts one parameter, limit, uses a for loop to sum up the integers from 1 to limit, and then returns the sum. As you can see, there is absolutely no code in the method to create a graphical user interface.

Nevertheless, since the Methods class extends the Java Power Framework class JPF, when the program is run a button is created to execute this method and after this button is clicked the following automatic GUI for evaluating the method is shown:

Sum Of Int GUI

You can see that the green arrow indicates where the argument should be entered (we used 1000) and the red arrow indicates where the result is returned (in this case 500500). The order of argument(s) on the right and return on the left mimics the structure of a method header.

The third method in the class named DrawShapesAndText illustrates both how to put shapes and text into a graphics window and how to put the same kind of objects into panels.

The method creates 2 circles and 1 square and handles each of these differently to illustrate the options. The first circle is added directly as a Paintable to the graphics window so it is entered as an object with default settings, that is, its outline is shown in black and it has no fill. The second circle is installed into a ShapePaintable explicitly so one can set the defaults. We choose a red fill and blue outline. Finally, the square is painted in red on the background layer of the graphics window and therefore is not represented as an object in the window object. Rather some pixels have been painted red and that is it.

The method also puts a simple text string into the window as a Paintable object.

Since the method enables automatic mouse listening in the graphics window, we can drag all of the items that were entered into the window as objects, namely, the 2 circles and the text string. We cannot drag the square since it is painted on the background layer and is not represented as an object floating above the background layer.

The situation is illustrated by the next two snapshots.

Shapes And Text Snapshot 1

The initial drawing after clicking DrawShapesAndText

Shapes And Text Snapshot 2

The drawing after dragging the 2 circles and the text string

Since we had already created the 2 circles, the square, and the text string, we decided to show how easy it is to put such objects into panels and then to show these panels. The screen snapshots below illustrate this.

Panel 1 named Funky Panel

The panel named “Funky Panel” is built using a VTable which is a class that specializes in vertical panels.

Panel 2 named Extra Panel

The panel named “Extra Panel” is built using a TablePanel which is a class that handles 1-dimensional or 2-dimensional tables.

Back to the Top

Down to the Bottom

9/19/06: Class Foo: A miniature Java tutorial

This class uses two very simple Java files Foo.java and Methods.java to illustrate a simple class and its testing.

The class Foo is a tiny class that illustrates the elemental aspects of creating a class in Java. Here is the entire code:

/* @(#)Foo.java   14 September 2006 */

/* Useful imports */

import edu.neu.ccs.console.*;

public class Foo implements ConsoleAware {
    public int x = 0;
    public int y = 0;
    
    public Foo() {}
    
    public Foo(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void print() {
        console.out.println("x: " + x);
        console.out.println("y: " + y);
        console.out.println();
    }
    
    public void print(String header) {
        if (header != null)
            console.out.println(header);
        
        print();
    }
}

The class is almost pure Java except that we have introduced the JPT console object for writing the print methods that will permit testing. The class is made aware of the console object via the phrase implements ConsoleAware in the class definition.

The class is elemental since it defines two simple instance variables named x and y of type int, two constructors both named Foo which is exactly the name of the class, and two functions or instance methods both named print. Things could hardly be much simpler.

Even with such a simple class, you may still be puzzled about a very fundamental question:

What exactly does a class definition do?

The simplest description might be to think of a class as an entity that collects things such as variable definitions, function or method definitions, and rules for construction. However this view is somewhat simplistic since thinking of a class merely as a collection box ignores the planning and intelligence that goes into the design of a class and its subsequent usage.

A better description of a class is as a set of architectural plans for the construction of one or more objects. Such plans specify the elements of structure or data that the object should possess plus the behavior that the object will exhibit. It is quite important to distinguish a class, that is, a set of plans, from the objects or instances constructed from these plans.

In the Foo, there are two structural elements defined, namely, the instance variables x and y of the primitive type int. These are initialized to a default value of 0 but this value may be changed in a constructor or later on since the instances are public.

In a class with more complexity, a class instance variable may be of a type defined by a class. Thus, in general, a class may be built by composition from primitive instance data and/or instance data whose type is defined by one or more classes. In fact, a class may include an instance variable that directly or indirectly refers to another object of the same class. This ability permits the definition of sophisticated data structures.

Class Foo provides two constructors. The first constructor has no parameters and is called the default constructor. In this example, the default constructor does absolutely nothing so the instances variables remain set to 0.

Let's look more closely at the second constructor:

    public Foo(int x, int y) {
        this.x = x;
        this.y = y;
    }

This constructor requires two parameters int x, int y. These parameters are not supplied by the Foo class itself but by whatever code uses the Foo class. Generally, the code that uses a class is referred to as a caller or client.

Notice that the parameter names x and y are identical to those of the instance variables. Although this may seem confusing, many programmers feel that it is also helpful since it suggests how the parameters should relate to the instance variables. Within the body of this constructor, we must of course know how to distinguish the parameters from the instance variables. We do this by writing this.x and this.y to mean the x and y that belong to this object. In Java, this acts as a name by which an object can refer to itself just as, in English, people can say “I” or “me” to refer to themselves. The period is also important since it signifies access. Thus, for example, the phrase this.x means access this object’s x.

The parameter data gets stored into the instance data by means of two assignment statements:

        this.x = x;
        this.y = y;

It is quite unfortunate that the mathematical symbol = is used in Java to signify assignment. This notation originated in the C programming language and has spread to many of the successors to C. The problem is that = is a symmetric operation in mathematics (a=b is the same as b=a) and is used to perform a test for equality. In contrast, in programming, assignment is absolutely not symmetric and furthermore the effect of assignment is to change the left hand argument using data from the right hand argument and not to simply perform a test.

Let's try to describe simply but precisely what assignment does. We may view assignment as a statement of the form:

    LHS = RHS

In this statement, LHS must designate a storage location, that is, it must name a variable that stands for a primitive type, a variable that refers to an entire object, an instance variable reference within an object, or an array cell reference.

RHS can be any of the kind of entities that LHS can be but RHS may also be more general. RHS may also be an expression that performs a computation or the return value of a method call.

In general, when the assignment is done, RHS is evaluated and the value is transferred to LHS. How the value is transferred depends on the type of LHS. If LHS is primitive, then the value is copied directly into the storage associated with LHS. If LHS is a reference to some form of object then only the minimal information needed to store the new reference is copied but not the entire object. This makes using objects quite efficient since assignment avoids the overhead and drawbacks of a complete copy of an object’s data.

Either way, LHS changes after an assignment. What was in LHS before the assignment is obliterated. If your program needs to remember what was in LHS before an assignment, you must use a separate assignment to copy that data elsewhere prior to doing the new assignment into LHS.

In contrast, if RHS is a variable, then it does not change under an assignment. Thus, assigment is not at all symmetric and you must be utterly careful in deciding what will be on the LHS (what variable is to change) and what will be on the RHS (what variable, expression, or function call will provide the new value for the LHS).

It is now possible to understand the two assignment statements in the second constructor.

    public Foo(int x, int y) {
        this.x = x;
        this.y = y;
    }

The first statement says to take the constructor parameter x and copy it into this object’s x. The second assignment says the same thing for y.

We may now complete our discussion of the simple class Foo by looking at the two print methods.

    public void print() {
        console.out.println("x: " + x);
        console.out.println("y: " + y);
        console.out.println();
    }
    
    public void print(String header) {
        if (header != null)
            console.out.println(header);
        
        print();
    }

Both methods use the JPT console object to print to the JPT console. The JPT console is convenient since you can easily change font sizes and also save the contents of the console window to a file. If you wish to use the built-in Java tools, replace console by System. Note that println prints what you ask for and adds a newline automatically. The out object also has a print method that just prints what you ask for and does not add the extra newline.

The first print method in Foo prints 3 lines consisting of the value of x, the value of y, and a blank line. The expression

    "x: " + x

takes the 3 character string x-colon-blank and appends the value of the instance variable x converted from its type int to a string. This expression syntax is built into Java and is quite convenient.

The second print method in Foo prints an optional 4th line with a header that identifies which Foo object is being printed. The header is passed in as a string. If the caller has made an error, the header might be uninitialized, that is, null. For safety, we check for this possibility and only print the header if it is in fact not null.

Note that the test for “not equals” is !=. If you are interested, the test for “equals” is ==. In other words, simple equality is tested using a pair of equals signs whereas a single equals sign is used for assignment. This peculiar set of conventions has been the bane of students and programmers for 30 years so you must take care to avoid the trap of using = when you want to test for equality via ==.

When the header is taken care of in the second print method, the method then calls the first print method to take care of the printing of the data. This technique avoids code duplication and is strongly recommended as a code style.

We now turn to the test class Methods.

/* @(#)Methods.java   14 September 2006 */

import edu.neu.ccs.jpf.*;

/** The sample starter class for Java Power Framework. */
public class Methods extends JPF 
{
    
    public static void main(String[] args) { 
        new Methods();
    }
    
    
    public void TestFoo() {
        Foo a = new Foo(2, 3);
        a.print();
        
        Foo b = new Foo(5, 7);
        b.print("b");
    }
}

Since the Methods extends the test framework class JPF, the test method TestFoo will give rise to a button in the JPF graphical user interface that then will execute the method. This automation makes testing extremely rapid and convenient.

What does TestFoo do? As you can see, it appears to both declare and construct 2 objects a and b built using the Foo class. It also prints these objects.

Let us examine the line Foo a = new Foo(2, 3); in detail.

The declaration part is Foo a. This states that a will either be a reference to an object of type Foo or will be null which represents an uninitialized object. If we in fact ended the statement here with a semicolon, a would be declared as a Foo object but would be uninitialized.

Since we continue with =, we see that we are about to do an assignment of the RHS into a. The RHS is an explicit construction and all explicit constructions must begin with the keyword new. After this, we must specify new what. We choose to make a Foo object which makes sense since a is a variable declared to refer to a Foo object. Since class Foo has two constructors, we have two choices for how to build the Foo object.

    Foo a = new Foo();        // default 0, 0
    Foo a = new Foo(x, y);    // x, y int

We choose the second format so we can set the instance variables to 2 and 3 respectively.

After building a with values 2,3, we print it, then we build b with values 5,7, and print it with the header “b”. This is what appears in the console:

x: 2
y: 3

b
x: 5
y: 7

Notice that the test method TestFoo acts as the caller or client that supplies the parameters to use in the operations requested from class Foo.

Back to the Top

Down to the Bottom

9/19/06: Sum Panel Variations

TextFieldView, TablePanel, SimpleAction, Halo

The methods file SumPanelTester.java

The vanilla sum panel file SumPanel.java

The sum panel file using the Halo wrapper SumPanelWithHalo.java

Before the detailed discussion, we will show screen snapshots of the two variations of the sum panel: vanilla and with halo.

Sum Panel Sum Panel With Halo
Vanilla Sum Panel Sum Panel With Halo

You can see immediately that the Sum Panel With Halo frame looks less crowded. We will discuss later why this is so.

Now let us discuss the code starting with SumPanel. The first block of code introduces the 5 text fields for the data x1, x2, x3, x4, and the total.

    private static int width = TextFieldView.getSampleWidth(20, '0');
    
    private TextFieldView view1 = new TextFieldView("0", width);
    
    private TextFieldView view2 = new TextFieldView("0", width);
    
    private TextFieldView view3 = new TextFieldView("0", width);
    
    private TextFieldView view4 = new TextFieldView("0", width);
    
    private TextFieldView total = new TextFieldView("0", width);

A TextFieldView is a JPT class based on Java’s class JTextField and its main purpose is to add robust I/O for multiple data types. As you can see, each text field is initialized to hold one character 0 and to have the same width. The width is computed first by a method that returns the width of a string with 20 zeroes. In other words, the text fields are designed to hold 20 digits.

The next block of code makes an object that encapsulates the behavior we wish to perform, namely, to sum the text fields x1, x2, x3, x4, and then place the result into the text field total.

    private SimpleAction sumAction =
        new SimpleAction("Sum Data") {
            public void perform() { sum(); }
        
    };

At first this code looks peculiar. It creates a SimpleAction object that is given a string name Sum Data and is also given a method definition, namely, the perform method is defined and its definition is tantamount to calling the sum method defined later in the class. Why this roundabout definition structure?

Our goal is to define the button Sum Data that you see in each of the snapshots. A button must have a label and a behavior to perform when it is clicked by the user. We know both of these. We want the label to be Sum Data and the behavior to be the sum method. The problem is that Java prohibits passing method names directly as arguments to anything so there is no direct way to tell a button what it should do! In some ways, this is an unfortunate restriction made by the designers of Java but we must all live with it. The solution to this dilemma is that we must construct an object that is expected to contain a method with a standard name, in this case, perform, and we implement perform by a one line call to the method sum that we really want to use.

At this point, Java takes over since it has a standard way to construct a button using an object of the general category of Action. We will see in a moment that JPT automates the final step from action to button.

The next blocks of code concern building the graphical user interface or GUI. You will notice that the 5 text fields have 5 corresponding labels and together these form a table with 5 rows and 2 columns. You can also see that the button is centered below this 5-by-2 table. We build the GUI in two steps. We make a 5-by-2 table object for the labels and text fields and then we insert this table into a vertical table with the action/button below. Here is the code.

    private Object[][] dataStuff =
        new Object[][] {
            { "x1", view1 },
            { "x2", view2 },
            { "x3", view3 },
            { "x4", view4 },
            { "total", total }
    };
    
    private TablePanel dataPanel =
        new TablePanel(
            dataStuff, 10, 10, WEST);
    
    private Object[] mainStuff =
        new Object[] { dataPanel, sumAction };
    
    private TablePanel mainPanel =
        new TablePanel(
            mainStuff, VERTICAL, 10, 10, CENTER);

The first step in making the 5-by-2 table is to create a 2-dimensional array with 5 rows and 2 entries per row. Each row consists of a label and its corresponding view. This is what is done in the definition of dataStuff. This is the raw material for building the 5-by-2 table.

The next step is to create the table dataTable using the data dataStuff. The constructor specifies the data, a horizontal and vertical gap between cells of 10, and an alignment of WEST which means that within cells objects are pushed towards the west or left edge.

The next step is to combine the dataTable with the action sumAction to make a second data array in preparation for making the outer table. This is what is done in the definition of the 1-dimensional array mainStuff.

Finally, we create mainTable using mainStuff. Since the array is 1-dimensional, we must specify a direction HORIZONTAL or VERTICAL. We choose VERTICAL in this case. For alignment, we specify CENTER which is how we get the button to be centered under the 5-by-2 table.

One powerful feature of TablePanel is that it can accept general objects such as String (the labels) or Action (sumAction) and figure out how to make them into the appropriate GUI components. Thus sumAction is used to automatically construct the button that uses the action name for the button label and the perform method for the button behavior.

The next step is the constructor for the SumPanel. The constructor completes any initialization steps that cannot be conveniently done in the earlier member data definition steps. Here is the constructor.

    public SumPanel() {
        add(mainPanel);
        addListeners();
        
        frame("Sum Panel");
    }

To understand this, let us also look at the class header.

    public class SumPanel extends TablePanel

This shows that SumPanel is also a TablePanel. The first line of the constructor says to take mainPanel and make it the single component within the SumPanel which acts as a wrapper. This style of building all the pieces of the GUI in the data definitions and then having one add statement to wrap things up is a very common idiom in JPT code.

The second line of the constructor calls the addListeners() method that we will describe below.

The third line of the constructor says to take the SumPanel and place it in a frame, that is, a full-fledged window on the screen that has Sum Panel as its title. This frame is centered on the screen by default. We call the process of taking a panel and putting it into a frame self actualization since it avoids the traditional Java step of separately constructing the frame and inserting the panel into its so-called content pane.

Let us finally look at the methods in this class of which there are only two. The first method, sum(), does the algorithmic work of the class since it implements the behavior in sumAction.

    private void sum() {
        double x1 = view1.demandDouble();
        double x2 = view2.demandDouble();
        double x3 = view3.demandDouble();
        double x4 = view4.demandDouble();
        
        double x = x1 + x2 + x3 + x4;
        
        total.setViewState(x + "");
    }

In the first four lines of sum(), we obtain the four values to be summed. The method demandDouble() of the TextFieldView class is used. This method insists that the user provide valid numeric data and will use error dialog boxes until any mistakes are fixed. This is an example of a method provided in TextFieldView that is not available in Java base class JTextField.

The next line does the mathematics of summation.

The final line converts the number x to a String via the Java idiom x + "" and then places the String into the total text field using the method setViewState which is also defined in TextFieldView.

The second and last method, addListeners(), is present for the convenience of the user. A text field will listen for a special event, namely, if the user presses the return-key while the cursor is in the text field. If this event happens then any action that has been specified via addActionListener will be done. Thus, in this case, the summation action can also be triggered if the user presses return in one of the first four text fields. This means that the user does not actually have to click the Sum Data button.

    private void addListeners() {
        view1.addActionListener(sumAction);
        view2.addActionListener(sumAction);
        view3.addActionListener(sumAction);
        view4.addActionListener(sumAction);
    }

The method addActionListener is inherited by TextFieldView from the Java base class JTextField.

We now explain what a Halo does and why it is used. A Halo is a wrapper panel that surrounds another panel and provides a small border. Its primary use in JPT is to provide focus if a user makes an input error. By default, if an error occurs in a TextFieldView, JPT will highlight the smallest panel that surrounds the text field. This can sometimes be problematic. In the case of the SumPanel, the smallest panel surrounding any of the text fields is the 5-by-2 table panel. Thus, no matter where the error occurs, the entire 5-by-2 panel is highlighted. This is not so nice for the user.

The Halo class solves this problem by providing a small panel to wrap around what is inside it so error highlighting will be focused. Here is the change in the code to construct the array dataStuff to add the necessary Halo wrappers.

    private Object[][] dataStuff =
        new Object[][] {
            { "x1", new Halo(view1) },
            { "x2", new Halo(view2) },
            { "x3", new Halo(view3) },
            { "x4", new Halo(view4) },
            { "total", new Halo(total) }
    };

In this code, each Halo uses a default border size of 2 pixels all around each text field.

A Halo may also be used to provide an overall border to a panel. Here is the change to the code that accomplishes this.

        add(new Halo(mainPanel, 10, 10));

Here we use a larger border of 10 pixels all around the main panel.

With this, you have all of the changes between SumPanel and SumPanelWithHalo.

Additional Comments

The code in the sum panel examples was written in 2005 and we decided to leave the code as is. Let us comment here on the simplications possible with the additions in JPT 2.5.0.

First, classes were added to JPT to deal with horizontal and vertical table panels, namely, HTable and VTable. Since, mainPanel is vertical, it may be defined as:

    private VTable mainPanel =
        new VTable(mainStuff, 10, 10, CENTER);

Next, a large number of methods have been added to DisplayPanel to make it easy to add borders to panels. Since most JPT panels extend DisplayPanel, these methods are widely usable. This means that instead of wrapping mainPanel in a Halo to get an outer border, we can instead add the following line at the top of the constructor:

        mainPanel.emptyBorder(10);

More complex borders may be added with equal ease. The real purpose of the Halo class was to provide a small wrapper so that error highlighting would be focused about the field with an IO error. It was merely a trick to use a Halo for an empty border. That trick is now unnecessary.

Back to the Top

Down to the Bottom

9/19/06: Playing Cards

Playing Cards Snapshot

The screen snapshot above shows an execution of the Java program PlayingCards defined in the file PlayingCards.java. This program illustrates the following features of Java and JPT.

The playing cards are found on the JPT web site at:

http://www.ccs.neu.edu/jpt/images/jfitz_cards/

The ordering of the cards is hearts, diamonds, spades, and clubs, followed by 2 card backs and 2 jokers. This ordering is specified in the following file within that site:

imagelist.txt

There are additional “card fragments” on the JPT site but only the 56 images in “imagelist.txt” are downloaded into the PlayingCards program.

To obtain all 67 images on the site including the “card fragments”, use instead the file:

imagelistall.txt

The site from which the playing cards were originally downloaded is:

http://www.jfitz.com/cards/

We appreciate the public service that the JFitz site performs by making these playing cards available at no charge.

Back to the Top

Down to the Bottom

Added 12/1/06: Playing Cards Applet

Access to the Playing Cards Applet

The Java file PlayingCardsApplet.java

Back to the Top

Down to the Bottom

9/19/06: Sample Fonts

Font Sampler Snapshot

The screen snapshot above shows an execution of the Java program FontSampler defined in the file SampleFonts.java. This file is extremely simple:

/* @(#)SampleFonts.java   13 September 2006 */

import edu.neu.ccs.gui.*;


public class SampleFonts {
    
    public static void main(String[] args) {
        FontSampler.main(null);
    }
}

As you can see this class simply serves as a bridge to reach the class FontSampler which is installed in JPT. The main method of SampleFonts simply executes the main method of FontSampler. Therefore, to understand what is happening, you should look at the file FontSampler.java. This program illustrates the following features of Java and JPT.

Back to the Top

Down to the Bottom

Added 12/1/06: Font Sampler Applet

Access to the Font Sampler Applet

The Java file FontSamplerApplet.java

Back to the Top

Down to the Bottom

9/19/06: Visual Color List

Visual Color List Snapshot

For the purposes of information, JPT has a class named VisualColorList that shows a scrollable list of the named colors that are installed as static objects in the JPT class Colors. Originally, we planned to include the code of the VisualColorList class in these samples.

Instead, we realized that the class VisualColorList could be improved. We therefore provide the code for the improved class VCL.java. This code will replace the code in VisualColorList in the next release of JPT.

The scrollable color list in VCL shows a color swatch, the color name, the color RGB values in decimal, and the color RGB values in hexadecimal. The decimal values are separated by commas. The hexadecimal values are preceded by the symbol # and have no separators; this follows the convention for defining colors on the web.

In addition to the scrollable color list, class VCL provides a ColorView in which the user may enter a color using either decimal or hexadecimal RGB values. This view permits experiments in which a user can vary the parameters of a named color and see what happens visually.

This program illustrates the following features of Java and JPT.

Back to the Top

Down to the Bottom

Added 12/1/06: Color Applets

Access to the Color Applets

The Java file VCLandCB.java

The Java file VCLandCB_Applet.java

Back to the Top

Down to the Bottom

9/19/06: Functions and Plots

The class FunctionsAndPlots in the file FunctionsAndPlots.java is a Java Power Framework tester class that permits the user to explore expression evaluation, definition and evaluation of simple functions, and function plots. It may be viewed as a collection of ingredients that might be incorporated into a function plot program to be constructed at some future time.

The initial JPF GUI that is presented when the class FunctionsAndPlots is launched is shown below.

Function And Plots GUI Snapshot

The first GUI button “Evaluate” corresponds to the method:

    public double Evaluate(double x) {
        return x;
    }

When the “Evaluate” button is clicked, the GUI shown below is automatically generated:

Automatic GUI for Evaluate

As an example, we have shown in this GUI the evaluation of the famous mathematical constant known as the “Golden Ratio”. This automatic GUI is the fastest mechanism in JPT to make a panel for evaluation of double precision expressions.

The next GUI button “EvaluateInConsole” launches a method that performs a double precision evaluation loop in the console window.

The next five GUI buttons bring up more sophisticated GUIs to evaluate expressions and/or define simple functions. The GUI button “EvaluateExpression” permits the user to choose between three result types: BigInteger, double, and boolean. The next two buttons allow the user to define simple functions that will then be recognized in the expression parser. The final two buttons bring up GUIs that permit both function definition and immediate testing via expression evaluation. In the buttons with the phrase “...WithIO”, the user can save function definitions to disk. Here is the GUI created when the last of the five buttons is clicked.

Function Builder With IO Snapshot

In the top pane of the window, the function definition for cuberoot in terms of the built-in function root is shown. In the bottom pane, the result of testing cuberoot on 27 is shown. Note that, for visual purposes, we have brought up the prior definition of cuberoot to show both the definition and the test in one snapshot. Normally, once a definition is made, the text fields are cleared to prepare for additional definitions.

The “PlotFunctions” button launches an automatic GUI in which the user may enter 4 items.

The function names can be either those of built-in functions, simple functions added algorithmically, or simple functions defined interactively by the user. In the screen snapshot below, we show one built-in function sqrt and two simple functions cuberoot and fourthroot. The plot interval is from -4 to 4 and the number of subdivisions is 100.

Plot Test Automatic GUI Snapshot

In the screen snapshot below, you may see the plot results.

Plot Test Results

You will notice, in particular, that since sqrt and fourthroot are not valid for negative inputs, the plots simply skip these points for the two functions.

The final two buttons bring up GUIs for plotting a polynomial or a fourier series that is entered by giving coefficients.

The series of examples in this program deserves careful study and may inspire you to build more elaborate programs. In particular, I recommend that you check out how the data is acquired from the functions and then how the plots are done including scaling, grids, tick marks, and axes.

Back to the Top

Down to the Bottom

9/19/06: Class KeyLabelData

This example illustrates the definition and elaboration of a data structure. It consist of two classes.

The KeyLabelData data structure class is almost 100% pure Java. The main aspect of the class that relates to JPT is that we require that the class implement Stringable which is an interface that requires a method to save the object data to a suitable string and a method to read the data back from a correspondingly structured string. Internally, we use JPT to make the coding of some of the methods faster and easier.

The purpose of the KeyLabelData is to associate a “search key” string with a list of strings or “labels”. The inspiration behind this class is a class that would store the address label information for a contact information program and would attach a search key to each contact to make it easy to search for particular contacts. The class is written in a more general way so that any kind of string information may be associated with a search key. There is one simplication, namely, that the number of labels that may be associated with a particular search key is fixed at the time of construction. This makes some code easier. A nice feature of the search is that the search key is automatically broken into individual words and one can search for any word by giving a string of characters that start the word. It is not necessary to type the full word.

Rather than discuss the KeyLabelData class line by line, we are going to outline the class and tell you what to look for in examining its code.

The class has 4 constructors that require varying amounts of data.

The constructors are coded so that the first three make use of the last constructor to minimize repeated code.

The capacity may not be changed after construction. On the other hand, both the key and the labels may be changed and there are assorted set methods to accomplish this. There is also an append method to add a label to the list.

The class has get methods to retrieve information about what is in the class.

The class implements “search recognition” by a method with the following signature:

    public boolean keyStartsWith(String string)

This methods returns true if the given string starts any word in the search key. The search is case-insensitive so it can find more matches.

The standard Java method toString() is implemented to return a string that combines all labels each terminated with a newline. Hence it may be viewed as the multi-line string of labels.

The Stringable method toStringData() makes a string by combining the search key plus a newline with all labels also terminated by a newline. It should be clear that this string contains all of the critical information within the object.

The Stringable method fromStringData is designed to reverse the effect of toStringData() to set the key-label content of the data structure from a string.

Since we have chosen to make the capacity of this data structure fixed at construction time, we do not include the capacity in the strings returned by toString() and toStringData(). This is considered internal information.

Finally, the class implements a compareTo methods that allows the class to implement the Comparable interface. This in turns permits objects of the class to be sorted.

By Java convention, compareTo should normally be consistent with the equals method and, in turn, this method should be consistent with the hashCode method. This leads us to also define the latter two methods.

From this summary, you can see that the class has facilities for building objects in a flexible way and for setting, getting, searching, and sorting. Thus, it is a simple but rather typical data structure class.

You may examine the tester class Methods for yourself. You will see that the tests are reasonably simple. You will see that one construtor and many methods are tested explicitly. In addition, since object data is printed explicitly in the tests, you can see that other behavior has also taken place correctly.

We hope to build classes related to KeyLabelData in future examples.

Back to the Top

Down to the Bottom

9/20/06: Tic Tac Toe

The Tic Tac Toe game is elementary and so provides a simple setting in which to illustrate some additional ideas in GUI building. Before further discussion, let us show two screen snapshots from the demo program.

TicTacToe image with a winner       TicTacToe image with a tie

In the first screen snapshot, player X has won the game and the winning sequence is highlighted in yellow. In the second screen snapshot, the game has been played to a tie since neither X nor O has won and no more moves are possible.

The game uses the concept of a tile that has a size, an object that is painted, and a background color. There are actually three kinds of tile: the blank tile that just paints the background, the X tile, and the O tile. Notice that the same object may be painted on several tiles. This distinction is important and is reflected in the code. The three things that are painted (blank, X, O) are Paintable objects that remain the same throughout the program. The 9 tile objects that are visible in the GUI are TileBox objects that can change their internal Paintable object and so can change what they display. In particular, as long as the game is not over, if a blank tile is clicked then it will change to an X tile or an O tile depending on what player has the next move. Technically, the tile does not change its identity only its Paintable contents.

The tiles are arranged in a 3-by-3 grid using a PaintableSequence. The initialization code creates a 3-by-3 array of TileBox objects each with a blank as its contents and burlywood as its background color. Using the move command, these tiles are geometrically positioned before being added to the seqeunce.

The PaintableSequence is in turn placed into a PaintableComponent which is an extension of the Java JComponent class designed to hold objects that are Paintable. A PaintableComponent entity is also set up to permit the easy definition of desired mouse actions.

The mouse code that controls the game is quite simple. When the mouse is clicked on the PaintableComponent, several checks are made. If the game is over or if the mouse has not hit a blank tile, then the mouse code does nothing. On the other hand, if the mouse has hit a blank tile, then the contents of that tile is changed to an X or O depending on what player is next and then the next player is switched to its opposite. After each click, a check is made to see if the game has been won or if no more moves are possible.

In effect, one can think of the tile grid embedded within the PaintableComponent as a complex button that responds to mouse clicks in a subtle fashion that depends on what particular tile is clicked. This contrasts with an ordinary button that behaves in the same way no matter where the mouse is clicked within the button. The mouse click code illustrates how complex behavior may be coded in a rather simple fashion.

Access to the Tic Tac Toe Applet .

Here is the Java file TicTacToe.java

Here is the Java file TicTacToeApplet.java

Back to the Top

Down to the Bottom

9/21/06: Fibonacci Variations

The Fibonacci numbers are a sequence of numbers starting with 1 1 and having the property that each subsequent number is the sum of the preceding two numbers. Here are the first few terms in the sequence:

    1 1 2 3 5 8 13 21 34 55 89 144 233 ... 

This example concerns generating the Fibonacci numbers in a simple graphical user interface (GUI). The interface shows 3 successive terms in the sequence so you can see how the last term is the sum of the previous 2 terms. Here are 4 screen snapshots that show the start of the sequence and 3 successive executions of the “Next Fibonacci” button.

Fibonacci for index 2

Fibonacci for index 3

Fibonacci for index 4

Fibonacci for index 5

After clicking “Next Fibonacci” a number of times, we quickly realized that we wanted to be able to push forward rapidly in the sequence without having to click for each step individually. This led to the “Repeat Next ...”. Suppose, we wish to go to the Fibonacci of index 50. We click “Repeat Next ...”. Then the simple dialog shown below appears, we enter 50, and click “OK”.

Repeat dialog with index 50

What happens is that the next action is repeated until index 50 is reached. The result is shown in the screen snapshot below.

Fibonacci for index 50

If you continue to higher values of the index, a problem eventually occurs. The first time it occurs is at index 92. The situation is shown in the screen snapshot below.

Fibonacci for index 92

As you can see, the value of Fibonacci for 92 is negative. What has happened? The answer is that we have used data type long to do the arithmetic and this type does not have enough space to store the actual result. Instead, the value was computed but wrapped around to a negative number. Ouch!

There is a way to fix this. Java supports a type BigInteger that will maintain precision as long as Java itself has enough memory for the required storage. Given the amount of memory on modern systems, this is enough for some rather large computations. Here is the screen snapshot taken with the variation of Fibonacci that uses BigInteger.

Fibonacci using Big Integer for index 92

Here is the similar screen snapshot with Fibonacci for 200.

Fibonacci using Big Integer for index 200

Here is the Fibonacci source code that uses long: Fibonacci.java

Here is the Fibonacci source code that uses BigInteger: FibonacciBI.java

Let us suggest some questions for you to consider as you examine and compare both source files.

Here are some suggestions that might inspire further projects. The first two are simple and the last two require substantially more thought and work.

Back to the Top

Down to the Bottom

9/26/06: Ball Animation

The Ball Animation should be viewed as a demonstration program that reveals the pattern for building animations using JPT. What is animated is a simple ball that moves back and forth on a horizontal track. There are slider controls that determine the step size, that is how many pixels the ball moves in each step, and the speed, that is, how many steps are executed per second. What is animated is intentionally very simple so the pattern can be shown in as clear a fashion as possible.

Here are two snapshots from the Ball Animation program:

The ball animation at startup

The Ball Animation at Startup

The ball animation running

The Ball Animation Running

The initial settings for the ball animation are a step size of 1 pixel and a speed of 1 step per second. With these settings, the animation will be very slow. At the opposite extreme, the step is 10 pixels and the speed is 100 steps per second or as close to that as the processor will permit. Visually, the ball will blur at that speed.

We will now discuss the design of the ball animation program whose source may be obtained at BallAnimation.java. We will separate a discussion of the GUI aspects from the deeper issues of how to program the animation using a separate “thread”.

GUI Design

The GUI consists of 3 levels: the animation track with the moving ball, the slider controls for step size and speed with their labels, and the buttons that run and stop the animation.

The ball is constructed as a ShapePaintable using an XCircle object to define the circle shape and associated settings to select red fill with blue boundary. This ball is inserted into a PaintableSequence for two reasons. First, this is the pattern that will needed to animate more than one object. Second, we can set the default bounds of the sequence to be what we wish as the size of the track along which the ball will move. Then, we insert the sequence into a Tile object that sizes itself to the bounds of the sequence and provides the light gray background that is the visual representation of the track. When the tile is in turn inserted into the GUI, it will automatically be placed within a PaintableComponent object that will take care of the repaint operations needed when the ball is moved.

The slider controls use the JPT class SliderView which is a minimal extension of the Java class JSlider. The extras in SliderView allow one to specify the actions to be performed as the slider is sliding and when the slider is released. The Java base class provides a method for defining the spacing of the tick marks and a simple JPT method allows these marks to be labeled. There is no provision in the slider classes for displaying the value of the slider as text so this is done with the labels to the right of each slider. Although the sliders appear to permit a slider value of zero, methods in the class intervene to guarantee that the minimum value of each slider is one. This avoids a division by zero.

The “Run Animation” button is constructed using a ThreadedAction to guarantee that the animation is done in a separate thread. What this means is discussed in a moment. The “Stop Animation” button is built using a SimpleAction in a manner familiar from earlier samples on this site.

Animation and Threads

A thread of execution is a collection of program instructions that conceptually appear to act as a unit that does work, looks at or changes data, and interacts with the user, the file system, and perhaps the network. All modern operating systems permit multiple programs to run at once so a user can surf the web, read e-mail, write a document, or manipulate an image all at once. Each program conceptually runs in one or more threads of execution that are distinct from those of all other programs currently running. It is the responsibility of the operating system to split time between all programs so each gets some slice of available processing time and appears to have control of all system resources while it is actually processing.

A simple program uses only a single thread of execution. For a program with a GUI, this thread must pay attention to and respond to the user actions such as typing keys and using the mouse. For this reason, this first thread is often called the “GUI thread”. If the program make few demands on the system then it can do all of its work, that is, run all its algorithms, within the GUI thread. So little is done that the user doesn't even notice any problems. However, if it turns out that the algorithmic work is intensive, then that work will consume all processor cycles allocated to the program and the program will have no cycles to pay attention to the user. In effect, the GUI will appear to freeze or die.

The solution to the problem of GUI freeze is to run intensive algorithms in a second thread independent of the GUI thread. Then the operating system will split time between the two threads provided that the busy thread agrees to take periodic breaks or pauses. This will permit the GUI thread to get needed processor time and therefore to remain alive.

Animation tends to be processor intensive so an animation program should be planned in such a way that the animation is done in a second thread. Java has a specific pattern for setting up a separate thread. Since the lines of code are always the same, we introduced in JPT the class ThreadedAction that incorporates this code. The key idea is that a ThreadedAction encapsulates an ordinary action but guarantees that each time it executes a new thread will be automatically created to execute the ordinary action it references internally.

Let us see how simple this turns out to be.

Here is the code that sets up the ThreadedAction object that will run the animation in a separate thread.

    private ThreadedAction runAction =
        new ThreadedAction
            (new SimpleAction("Run Animation") {
                public void perform()
                { runAnimation(); }
    });

The ThreadedAction constructor must be provided with an ordinary action that it will use to define the behavior that will be executed on the separate thread. As you can see above, we provide this ordinary action by creating a SimpleAction and that action in turns calls the method runAnimation(). The fact that the behavior will run in a separate thread is now 100% automatic.

The action to stop the animation runs quickly so it does not need to be run in a separate thread. It can be defined simply via a SimpleAction.

    private SimpleAction stopAction =
        new SimpleAction("Stop Animation") {
            public void perform() { stopAnimation(); }
    };

Here is the code for the methods runAnimation(), stopAnimation(), and related helper methods.

    /**
    The animation loop method that will
    execute in a separate thread.
     */
    private void runAnimation() {
        // set state for run
        setRunState();
        
        // perform animation
        while(true) {
            synchronized (animationLock) {
                if (!running)
                    return;
                
                animate();
            }
            
            JPTUtilities.pauseThread(getDelay());
        }
    }
    
    /**
    The method to stop the animation loop.
     */
    private void stopAnimation() {
        // set state for stop
        setStopState();
        
        // perform any desired cleanup activities
    }
    
    /**
    Set the enable/disable state of the actions
    for the Run state.
    
    Set boolean running to true.
     */
    private void setRunState() {
        synchronized (animationLock) {
            runAction. setEnabled(false);
            stopAction.setEnabled(true);
            
            running = true;
        }
    }
    
    /**
    Set boolean running to false.
    
    Set the enable/disable state of the actions
    for the Stop state.
     */
    private void setStopState() {
        synchronized (animationLock) {
            running = false;
            
            stopAction.setEnabled(false);
            runAction. setEnabled(true);
        }
    }

To understand this, first keep in mind that the actions runAction and stopAction will be used to build the buttons “Run Animation” and “Stop Animation” in the GUI. Clicking the buttons will execute the actions. This will help us explain the pair of helper methods. The method setRunState():

Symmetrically, the method setStopState():

The effect of this is that when the animation is running then the “Run Animation” button is disabled so you cannot start yet another thread in conflict with the already running thread. At the same time the “Stop Animation” is enabled so it is possible to stop the animation. When the animation is stopped, then the state of the buttons is reversed. This is visible in the two screen snapshots above.

Now let us look carefully at runAnimation().

    /**
    The animation loop method that will
    execute in a separate thread.
     */
    private void runAnimation() {
        // set state for run
        setRunState();
        
        // perform animation
        while(true) {
            synchronized (animationLock) {
                if (!running)
                    return;
                
                animate();
            }
            
            JPTUtilities.pauseThread(getDelay());
        }
    }

The method setRunState() is run once and then the code enters an infinite loop signaled by while(true). Hence, unless something intervenes, this code will run forever. Notice, however, there is an immediate test of the control variable named running. If this variable is false, the loop will exit.

You may ask, how can the variable running become false if there is no code within the infinite loop to change the variable? The answer is that the variable can become false if the “Stop Animation” button is clicked. This click is recognized in the GUI thread which is running in parallel to the animation thread. The keyword volatile is added in the declaration of the variable running to alert the compiler that running may be altered by different threads and to therefore avoid compiler optimizations that would eliminate the test.

If running is true then the test fails and the loop continues on to execute the animate() method. The code has been written in this way to create a pattern that you can follow if you want to do your own animation. All you need to do is set up your own situation and write you own version of animate().

Now comes a crucial step. The animation thread must pause to give the GUI thread some life and to control the animation speed. The following method call is made:

            JPTUtilities.pauseThread(getDelay());

This code tells the current thread (which is in fact the animation thread) to pause for the amount of milliseconds given by its parameter. The delay time is computed by the method getDelay() which uses information from the speed slider and simple arithmetic. It might be computed quite differently in your animation program.

Finally, what about the phrase synchronized (animationLock) that occurs in several places? This code resolves issues of conflict. If more than one thread is working with certain data, then it is possible to get that data into an inconsistant state by starting an update to the data in one thread and then switching threads before the update is complete. When a section of code is synchronized relative to some “lock” object, then it can complete its work before any other thread that synchronizes on the same object is allowed to proceed with its work. This ensures that data is updated correctly. It doesn't actually matter what the “lock” object is. What is crucial is that sections of code that work on common data use the same lock object for synchronization. One more point. The call to pauseThread is not within the scope of synchronization. If it were, the “Stop Animation” button could never actually execute its code and the animation could never be stopped. Thus the details of the pattern are very critical.

One additional technical point. If you close the Ball Animation window, this will terminate the GUI thread. Look through the program to see how the closing of the window also ensures that the animation thread comes to a halt.

Hopefully, the Ball Animation can provide a pattern to follow if you wish to explore animation.

Back to the Top

Down to the Bottom

Added 12/1/06: Ball Animation Applet

Access to the Ball Animation Applet

The Java file BallAnimationApplet.java

Back to the Top

Down to the Bottom

10/4/06: Table of Factorials

The JPF test file Methods.java contains two variations of a method that will print a table of the factorial function from mathematics. Let us first review what the factorial function is.

Here is a table of the factorials from 0 to 10.

    0! = 1
    1! = 1
    2! = 2
    3! = 6
    4! = 24
    5! = 120
    6! = 720
    7! = 5040
    8! = 40320
    9! = 362880
    10! = 3628800

The notation n! reads “n factorial” and stands for the definition:

    n! = 123...(n-1)n

By convention, 0! = 1

For positive n, there is an “inductive formula” that lets you compute n! from (n-1)!:

    n! = n(n-1)!

This formula is the basis for the methods in the Java file given above. It says that if you already have (n-1)! then you can compute n! using a simple multiplication.

Since the factorial function grows quickly, we want to use so-called “big integers” rather than int or long to store the computations. There are two options: the Java class BigInteger or the JPT class XBigInteger. The Java file above shows both variations so you can pick a style that you would prefer to use in similar situations.

Since the Java file is heavily commented, we will simply let you read it for yourself.

Back to the Top

Down to the Bottom

10/5/06: Classic Shapes

The JPF test file ClassicShapes.java illustrates how to constructs what we will call the 7 classic shapes: rectangle, rounded rectangle, oval, square, rounded square, circle, and line. These correspond to the following JPT and related Java classes:

    JPT             Java
    XRect           Rectangle2D.Double
    XRoundRect      RoundRectangle2D.Double
    XOval           Ellipse2D.Double
    XSquare             no corresponding Java class
    XRoundSquare        no corresponding Java class
    XCircle             no corresponding Java class
    XLine2D         Line2D.Double

As you can see, the JPT class names are much more consise than the Java names. The reason the Java names are so complex is that Java wanted to provide both Double and Float variations of the shapes. JPT simply uses double.

The constructors for XRect and XOval use parameters x y w h where x and y are the coordinates of the left-top corner of the bounding box and where w and h are the width and height of that box. The constructor for XRoundRect adds two extra parameters that provide the rounding radii in the x and y directions respectively.

The constructor for XCircle uses x y r where x and y are the coordinates of the center of the circle and r is its radius. The classes XSquare and XRoundSquare also use the center rather than the left-top corner. For these classes, the radius means the radius from the center of the square to its side so in fact is one-half of the side. The XRoundSquare also adds to its constructor the arc radius for rounding the corners.

The constructor for XLine2D uses x1 y1 x2 y2 which represent the coordinates of the endpoints of the line.

Note that it is sometimes convenient to define a rectangle, rounded rectangle, or oval using the opposite corners of the bounding box. The classes XRect, XRoundRect, and XOval have a method setX1Y1X2Y2 that lets you define the bounding box using any two opposite corners. On the other hand, for squares and circles, this method and related methods that use the bounding box to define the object are changed to do nothing at all. This is because there is no valid way mathematically to use a rectangular bounding box to uniquely define a square or circle.

The classes for squares and circles may be viewed a trivial convenience classes since it is certainly possible to draw squares and circles with the rectangle and oval classes.

Here is a screen snapshot with the execution of the ShapeSample method in the file ClassicShapes.java.

The sample of 7 classic shapes

You should examine the file to see:

Back to the Top

Down to the Bottom

10/5/06: GeneralPath Shapes

Java has a very powerful shape class named GeneralPath that permits a user to build up a shape as a path consisting of segments that may be added incrementally. JPT builds on this foundation to provide several shape related classes that improve convenience. First, let us describe GeneralPath.

The class GeneralPath has three constructors that are the most useful.

GeneralPath() that creates an empty path with the default winding rule WIND_EVEN_ODD.

GeneralPath(int windingrule) that creates an empty path with the specified winding rule.

GeneralPath(Shape shape) that initializes the path using the data in the given shape.

What is the winding rule? This is a constant that specifies the mathematical algorithm that will be used to fill the shape with color or paint should that be desired. The even-odd rule is the easiest to compute. For each horizontal line, you travel from left to right and consider a point to be within the shape if you have crossed the path an odd number of times. The more subtle rule is based on the so-called winding number. A point is viewed as within the path if the path winds around the point a non-zero number of times. This rule is harder to compute but there do exist reasonable methods to accomplish the task. Java prefers the easier rule WIND_EVEN_ODD but as a mathematician I prefer the rule WIND_NON_ZERO which may capture more points. If the path does not cross itself, both rules give the same result.

Java specifies the winding rule to use via 2 integer constants that are named as follows.

GeneralPath Constants

GeneralPath.WIND_EVEN_ODD: 0
GeneralPath.WIND_NON_ZERO: 1

The winding rule may be changed after a GeneralPath is constructed by the method setWindingRule.

What makes GeneralPath so powerful is that you can build up a path incrementally by one of 5 operations.

path.moveTo(x0, y0);
path.lineTo(x1, y1);
path.quadTo(x1, y1, x2, y2);
path.curveTo(x1, y1, x2, y2, x3, y3);
path.closePath();

When a path is being constructed, the first call must be to the method moveTo to initialize the start point of the path. If one of the other 4 operations is called first, the class will throw an exception.

A minor annoyance in Java is that the parameters must be float rather than double. This decision goes back to the early days of Java when programmers were quite concerned about saving space and performance. Nowadays, with more memory, space is not such a concern, and with mathematics chips it is actually faster to compute in double than in float.

The main impact of using float occurs when you write code and want a float constant. If you write, for example, 2.397, this will be interpreted as double. To inform Java that you want a float, you must write 2.397f. The extra f characters can be bothersome when you forget them. There is no need for the f if the constant is an integer.

We have created a sample file PathShapes.java that should help you to understand how to use the class GeneralPath.

The first method in this class is ShowQuadShape that creates a GeneralPath that moves to a start point x0,y0 and then constructs a quadratic curve using the 4 parameters x1,y1,x2,y2.

    public void ShowQuadShape
        (float x0, float y0,
         float x1, float y1,
         float x2, float y2)
    {
        GeneralPath path = new GeneralPath();
        
        path.moveTo(x0, y0);
        path.quadTo(x1, y1, x2, y2);
        
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.transparent;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, path, fill, draw, 2);
        window.repaint();
    }

Here is the input panel in which the 6 parameters are specified.

Sample data for quad shape

Here is the screen snapshot of the quad curve corresponding to these 6 input parameters.

Sample quad shape structure

Notice that the middle parameters x1,y1 correspond to a control point that is not on the curve itself. The control point together with the end points form a tent-like structure and the curve falls within the tent. We plan to talk about the algorithm that draws the curve in class since it is much easier to explain the drawing process live.

If you examine the graphics code, you will see a call to the JPT method Path.showShapeStructure. This method shows a path, the data points on the path, the control points, and the polygonal frame that connects the data and control points. The path may also be filled but in the above example the fill color was set to transparent. Behind the scenes, this method makes a special Paintable object that displays all of the features.

The next method in this class is ShowCubicShape that creates a GeneralPath that moves to a start point x0,y0 and then constructs a cubic curve using the 6 parameters x1,y1,x2,y2,x3,y3.

The portion of the code for this method that creates the cubic curve is:

        GeneralPath path = new GeneralPath();
        
        path.moveTo(x0, y0);
        path.curveTo(x1, y1, x2, y2, x3, y3);

Here is the input panel in which the 8 parameters are specified.

Sample data for cubic shape

Here is the screen snapshot of the cubic curve corresponding to these 8 input parameters.

Sample cubic shape structure

Notice that the middle parameters x1,y1 and x2,y2 correspond to a pair of control points that are not on the curve itself. The control points together with the end points form a zig-zag structure and the curve falls along this strructure. Again, we plan to talk about the algorithm that draws the curve in class since it is much easier to explain the drawing process live.

Our discussion of the drawing algorithms will be assisted by additional methods ShowQuadSubdivision and ShowCubicSubdivision that we will explain in class.

It is quite interesting to apply the above techniques to see how Java draws a circle. In fact, its turns out that Java uses 4 cubic segments to define a close approximation to a circle that can be drawn much more quickly. Here is the code:

    XCircle circle = new XCircle(200, 200, 100);
    
    public void CircleShapeStructure() {
        window.clearPanelAndSequence();
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.green;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, circle, fill, draw, 2);
        window.repaint();
    }

Here is the screen snapshot when this method is run:

Circle shape structure

This snapshot clearly shows that the circle is in fact approximated by 4 cubic segments.

It is interesting to “reverse engineer” the circle shapes to discover the 4 cubics used. To help with this, there is a method Path.shapeToString that will extract the internals of the shape and put this data into a string that may be printed. Here is the result of that process.

Circle Path Data

WIND_NON_ZERO
MOVE[300.0;200.0]
CUBIC[300.0;255.22847;255.22847;300.0;200.0;300.0]
CUBIC[144.77153;300.0;100.0;255.22847;100.0;200.0]
CUBIC[100.0;144.77153;144.77153;100.0;200.0;100.0]
CUBIC[255.22847;100.0;300.0;144.77153;300.0;200.0]
CLOSE[]

This print out shows that the circle with center (200,200) and radius 100 is being constructed as follows by Java.

GeneralPath path = new GeneralPath();

path.moveTo (300.0f,     200.0f);
path.curveTo(300.0f,     255.22847f,  255.22847f, 300.0f,      200.0f, 300.0f);
path.curveTo(144.77153f, 300.0f,      100.0f,     255.22847f,  100.0f, 200.0f);
path.curveTo(100.0f,     144.77153f,  144.77153f, 100.0f,      200.0f, 100.0f);
path.curveTo(255.22847f, 100.0f,      300.0f,     144.77153f,  200.0f, 300.0f);

By naming the important parameters, we can take a more abstract view of this circle data and come to a better understanding of how it is structured. Let:

x be the x-coordinate of the circle center (200 in the example)

y be the y-coordinate of the circle center (200 in the example)

r be the radius of the circle (100 in the example)

k = 0.5522847f be the cubic control constant for a circle

s = kr be the radius of the circle multiplied by the constant k (55.22847f in the example)

We will now describe the 13 points that occur in the above specifications for a circle in more abstract terms. By a vertex, we mean a point that lies on the path. By a control, we mean a point that controls the shape of a curve in the path but is not on the path.

x-coordinate y-coordinate type location
x + r y vertex east
x + r y + s control ese
x + s y + r control sse
x y + r vertex south
x - s y + r control ssw
x - r y + s control wsw
x - r y vertex west
x - r y - s control wnw
x - s y - r control nnw
x y - r vertex north
x + s y - r control nne
x + r y - s control ene
x + r y vertex east

The above table shows that there is a very systematic way in which the coordinates of the vertices and control points are computed based on the constant k. This constant has been chosen so that the cubic segments will provide the best possible approximation to the corresponding circular arcs.

We wish to pose a question that you may wish to puzzle about and then follow up with experiments. An ellipse aligned along the axes is characterized by two radii, the radius a parallel to the x-axis and the radius b parallel to the y-axis. How would the above structural description of the circle need to be generalized to provide a similar description for the ellipse with radii a and b?

We conclude this section with a final example that represents a more complex path. Its code is:

GeneralPath path = new GeneralPath();
        
path.moveTo(100, 100);
path.lineTo(300, 100);
path.quadTo(350, 200, 300, 300);
path.curveTo(250, 225, 150, 375, 100, 300);
path.closePath();
        
path.moveTo(100, 50);
path.lineTo(200, 75);
path.lineTo(300, 50);
path.closePath();
        
path.moveTo(50, 100);
path.curveTo(90, 300, 10, 300, 50, 100);
path.closePath();

You should compare this code with the screen shapshot below to match points in the code with data and control points in the snapshot. This will make your understanding of paths more complete.

More complicated sample path

Back to the Top

Down to the Bottom

10/23/06: Curve Mathematics

We are going to provide a summary of the mathematics behind the curves provided in the Java class GeneralPath. We will focus on cubic curves since quadratric curves follow the same pattern but are simpler. Mathematically, the ideas generalize further, but Java provides no built-in implementation.

A cubic curve segment is defined by a start vertex point P0, two control points P1 and P2, and an end vertex point P3. In coordinates, we may view this as:

P0 = (x0, y0)
P1 = (x1, y1)
P2 = (x2, y2)
P3 = (x3, y3)

Java tends to work with the coordinates. Furthermore, when defining a cubic segment, x0,y0 are taken to be the current point in the path and the caller supplies just x1,y1,x2,y3,x3,y3 to the method curveTo. In most cases, we will try to use a more mathematical notation in terms of points but you must recognize that the formulas must be converted into pairs of formulas for the x and y coordinates.

The 4 points P0,P1,P2,P3 define a cubic polynomial curve P(t) in the parameter t as follows.

P(t) = (1-t)^3 P0 + 3 (1-t)^2 t P1 + 3 (1-t) t^2 P2 + t^3 P3

     = P0 + 3 t (P1 - P0) + 3 t^2 (P2 - 2 P1 + P0)
       + t^3 (P3 - 3 P2 + 3 P1 - P0)

Here, following mathematical convention, we separate factors by a space to indicate multiplication, and we let ^ stand for the “exponent” operation. Note that:

P(0) = P0  and  P(1) = P3

so the above formula defines a cubic polynomial curve in t that goes from point P0 to point P3 as t goes from 0 to 1. Therefore, the points P0 and P3 are vertex points of the curve. Furthermore, since the points P1 and P2 influence the cubic curve path, these points may be viewed as control points.

We will now describe the fundamental subdivision algorithm that permits the curve to be divided into two segments which may once again be defined by 4 points. This permits cubic curves to be recursively constructed with extreme efficiency. We will first describe the general case where the subdivision is based on a parameter t and we will then specialize to t = 1/2 which is what is used in practice.

Let 0 <= t <= 1. The subdivision algorithm is based on repeated linear interpolation. In general, if we are given two points A and B and the parameter t, then we can compute the point that is the fraction t of the way from A to B by the formula:

(1 - t) A + t B

Notice that when t = 0 this formula yields A and when t = 1 this formula yields B. Since the formula is a linear function of t, the result is called the linear interpolation.

The subdivision algorithm uses repeated linear interpolation. The following 6 points are constructed. We leave you to check the details of the algebra if you are so inclined.

Q0 = (1 - t) P0 + t P1 = P0 + t (P1 - P0)

Q1 = (1 - t) P1 + t P2 = P1 + t (P2 - P1)

Q2 = (1 - t) P2 + t P3 = P2 + t (P3 - P2)

R0 = (1 - t) Q0 + t Q1

   = P0 + 2 t (P1 - P0) + t^2 (P2 - 2 P1 + P0)

R1 = (1 - t) Q1 + t Q2

   = P1 + 2 t (P2 - P1) + t^2 (P3 - 2 P2 + P1)

S0 = (1 - t) R0 + t R1

   = P0 + 3 t (P1 - P0) + 3 t^2 (P2 - 2 P1 + P0)
     + t^3 (P3 - 3 P2 + 3 P1 - P0)

Notice that S0 equals the point P(t) on the cubic curve. Hence the subdivision algorithm can compute points on the curve. I consider this a mathematical miracle.

The screen snapshot below illustrates this construction. In the snapshot t = 1/2.

Snapshot of the cubic subdivision process

An even deeper mathematical miracle is what follows. Notice that we have 2 sequences of points P0,Q0,R0,S0 and S0,R1,Q2,P3 that may themselves be used to define cubic curves. The mathematical miracle is that these curves are precisely the left and right segments of the original curve when subdivided at the point S0 = P(t). This is why the process is called the subdivision algorithm. This property of the subdivision algorithm leads the way to the use of recursion.

For those of you who are interested, here is a more precise statement of the mathematical facts. Let Pa(u) be the cubic that corresponds to P0,Q0,R0,S0 and Pb(v) be the cubic that corresponds to S0,R1,Q2,P3.

Pa(u) = (1-u)^3 P0 + 3 (1-u)^2 u Q0 + 3 (1-u) u^2 R0 + u^3 S0

Pb(v) = (1-v)^3 S0 + 3 (1-v)^2 v R1 + 3 (1-v) v^2 Q2 + v^3 P3

Then the mathematical results which show that the 2 new curves correspond to segments of the original curve are:

Pa(u) = P(u t)

Pb(v) = P(t + v (1 - t))

We leave you to check the details of the algebra if you are so inclined.

In practice, the subdivision algorithm is usually applied with t = 1/2 because division by 2 is extremely efficient. Here are the formulas in this special case.

Q0 = (P0 + P1) / 2

Q1 = (P1 + P2) / 2

Q2 = (P2 + P3) / 2

R0 = (Q0 + Q1) / 2

R1 = (Q1 + Q2) / 2

S0 = (R0 + R1) / 2

When the subdivision algorithm is used to draw a curve or to define a curved region to fill, what happens is that subdivision is applied recursively until it is determined that a segment has been reached that is “flat enough” to be rendered as a straight line. The curve is then rendered as a polygon with many small straight lines.

We have created a demo program to illustrate Cubic Subdivision. This has an application version CubicSubdivision.java and an applet version CubicSubdivisionApplet.java that is based on the application.

Access to the Cubic Subdivision Applet .

To play with this demo, use the mouse to drag the red points that correspond to P0,P1,P2,P3. The structure drawing will transform smoothly as you drag one of these points. If you wish to see the numerical data, click to the “Cubic Data” pane.

As we were building this demo, we decided that it would be useful to students to capture the stages we used in separate text files. This would allow students to see how the demo was developed. We will provide links to each such stage file and briefly comment on what was done in that stage. The Java import statements have been deleted from these text files.

Stage1.txt

Stage 1 sets up the basic structure of the GUI. Our goal was to provide a pane to display the cubic structure and permit mouse interaction and a pane to provide the data for all of the points. Since we believed that there was not enough screen real estate to show both panes at once, we decided to use a Java JTabbedPane. At this stage, we only set up the pane for the cubic structure. Our plan was to use a PaintableSequence to hold the cubic, the 6 lines, the 10 squares for the points, and the 10 labels. To avoid problems of graphics inconsistency, we planned to replace the paintable sequence entirely rather than update it piecemeal and risk the chance of a partial screen update. Therefore, this stage also defined a Tile object that will serve as a wrapper for the paintable sequence. By setting the bounds of the tile, we can reserve the right amount of space in the GUI before the paintable sequence is even built. At this stage, the bounds were set to 600 by 600.

It turned out that there was an additional annoyance. The default background for a JTabbedPane turned out to be a shade of blue rather than simply white. For some reason, none of the Java commands to change colors had an influence on this blue background. We decided therefore to place the Tile into a PaintableComponent whose background we could set directly to white.

Stage2.txt

Stage 2 sets up the data for:

Stage 2 defines the following methods to work with this data.

At this stage, the points P0, P1, P2, P3 are fixed in their initial position since there is no mouse code for dragging these points.

Stage3.txt

Stage 3 adds the mouse behavior. If the mouse is pressed close to one of the 4 vertices P0, P1, P2, P3 then the particular vertex is noted and dragging is enabled. As the mouse is dragged, all that needs to be done is to update the position of the vertex and then call paintStructure. This demonstrates that adding mouse actions is easy if the underlying methods are already present.

Stage4.txt

Stage 4 adds the tabbed pane that shows the values of the 10 points P0, P1, P2, P3, Q0, Q1, Q2, R0, R1, S0. Originally, the plan was to use 4 rows for P’s, Q’s, R’s, and S0. However, this occupied too much horizontal width. Therefore, we decided to use a vertical layout with 10 rows. The data definitions show the traces of the earlier design but the new code is valid.

Stage 4 also introduced a check box to control whether or not the labels should be displayed. We found in experimentation that it was sometimes hard to see the geometry due to the labels. Thus, the ability to hide the labels was deemed essential.

Stage5.txt

Stage 5 was added to tidy up loose ends. After making the applet file, we decided that the cubic structure pane should be 500 by 500 rather than 600 x 600. This required us to change the coordinates of the some of the P’s. We also noticed a bug in that the mouse would not always drag a P-square. We realized that this was due to a difference in the size of a square from the distance used to test mouse closeness. We made both numbers equal.

Back to the Top

Down to the Bottom

10/26/06: Polygons and Cubic Curves

In the two previous sections, you have seen how to use the Java class GeneralPath to make shapes consisting of lines, quadratic curves, and cubic curves. Since you may also introduce move and close operations, you can make shapes with multiple sections. This is very powerful and general. However, there is no simplification in Java for constructing a shape that consists of a single section that is made up of only lines (a polygon) or only of cubic curves segments. In this section, we will show you how JPT makes these special cases easier.

Since a polygon consists of lines, there is no need for control points. On the other hand, to define a cubic curve one must either specify control points or employ an algorithm that will decide what the control points should be based solely on the vertex points. If such an algorithmically automated process provides control points that are “good enough” then much effort can be saved by the programmer and the user.

This section will focus on two JPT classes PolygonShape and AutomaticCurve that are the most useful in practice. JPT offers several other classes for more special needs.

Before we get into details, let us show a screen snapshot of the demo program that will illustrate these ideas.

PolygonsAndCubics Demo Snapshot

As you can see, the program will create a random shape that is either a polygon or a cubic curve with between 3 and 18 vertices. If you have selected one type of shape on construction you can switch to the opposite type by clicking on the shape radio button choices. Using the mouse, you can drag any of the vertex points to see how the shape changes.

There are two choices that apply to both polygons and cubic curves, namely, the decision about whether the shape is closed or open and the decision about the winding rule that determines the filled region. In this demo, you can flip these choices after the shape is built and see visually exactly what happens. We have discussed the winding rule above and the main thing to keep in mind is that “wind-non-zero” potentially considers more points to be in the shape region than the simpler rule “wind-even-odd”.

In the case of a cubic curve, you must also choose the algorithm that automatically computes the control points from the vertex points. JPT provides two such algorithms. The Bezier strategy chooses the control points to achieve “smooth second derivatives”. Once you learn calculus, this smoothness condition will make sense. The other strategy is the chord strategy that computes the control points using the chord joining the two adjacent vertices as a guide. This chord vector is multiplied by a numerical factor that controls how tight the curve is at each vertex. The smaller the factor the tighter the curve. Factors between 0.25 and 0.333333 tend to work best but you can experiment with other factors even negative ones.

The option to show labels lets you see where the polygon or curve starts. This is useful when you switch from a closed to an open shape.

Here is the source code for the Polygons And Cubics application PolygonsAndCubics.java and here is the additional code for the applet PolygonsAndCubicsApplet.java that is based on the application.

Access to the Polygons And Cubics Applet .

We will next talk about how to build a polygon shape using the JPT class PolygonShape. This class has several constructors but the most general one is:

public PolygonShape
    (float[][]        vertex,
     ClosureMode      closuremode,
     WindingRule      windingrule)

The options for ClosureMode are:

The options for WindingRule are:

Rather than use integers to specify these choices as in Java, we follow the modern practice of using classes with constant objects for each choice. This means that if you accidentally reverse the order of the choices in the above constructor, you will get a compiler error instead of merrily going forward to discover the error at runtime.

The data points for the polygon are specified by a 2-dimensional array of float that should have some number n of rows and have exactly 2 columns.

We have a sample file that illustrates some simple polygons: PolygonSamples.java.

The first excerpt from this file shows how to make the data for a diamond shape directly.

Color fill = Colors.red;
Color draw = Colors.black;


float[][] diamond =
    {  { 200, 100 },
       { 300, 200 },
       { 200, 300 },
       { 100, 200 }
    };


PolygonShape diamondShape =
    new PolygonShape(diamond);


ShapePaintable diamondPaintable =
    new ShapePaintable
        (diamondShape, PaintMode.FILL_DRAW, fill, draw);


public void ShowDiamond() {
    window.clearPanelAndSequence();
    window.appendPaintable(diamondPaintable);
    window.repaint();
}

The screen snapshot corresponding to the diamond code is:

Diamond shape image

The main point of the diamond example is that the diamond data can be entered directly in the definition of the float array. Thus, an array in Java can be initialized quickly in manner somewhat like a list in Scheme.

It is also possible to initialize a float array algorithmically. This is illustrated by the following example of a star.

float[][] star() {
    float[][] data = new float[5][2];
    
    float x = 200;
    float y = 200;
    float r = 100;
    
    int angle = 0;
    int delta = 144;
    
    for (int i = 0; i <= 4; i++) {
        float dx =   r(float) MathUtilities.sindeg(angle);
        float dy = - r(float) MathUtilities.cosdeg(angle);
        
        data[i][0] = x + dx;
        data[i][1] = y + dy;
        
        angle += delta;
    }
    
    return data;
}


PolygonShape starShape =
    new PolygonShape
        (star(), ClosureMode.CLOSED, WindingRule.WIND_NON_ZERO);


ShapePaintable starPaintable =
    new ShapePaintable
        (starShape, PaintMode.FILL_DRAW, fill, draw);


public void ShowStar() {
    window.clearPanelAndSequence();
    window.appendPaintable(starPaintable);
    window.repaint();
}

The screen snapshot corresponding to the star code is:

Star shape image

In the star code, the method star() constructs the float array that is used to make starShape. You will also notice that I used a brief constructor fot the diamond shape but the full PolygonShape constructor for the star. The reason is that I needed to specify the winding rule WindingRule.WIND_NON_ZERO since otherwise the star would not fill properly.

Returning to the Polygons and Cubics demo, the code to construct the shape is algorithmic. The data points are constructed randomly via the following method:

void setRandomPoints() {
    int n = getPointCount();
    
    points = new float[n][2];
    
    for (int row = 0; row < n; row++)
        for (int col = 0; col <= 1; col++)
            points[row][col] =
                MathUtilities.randomInt(0, size);
}

Here points is a float array member data variable defined earlier and size is the window size.

Once the points are defined, the shape is updated by the following method:

void updateShape() {
    String type = getShapeType();
    ClosureMode mode = getClosureMode();
    WindingRule rule = getWindingRule();
    
    if (type == POLYGON) {
        shape = new PolygonShape(points, mode, rule);
    }
    else {
         String tangenttype = getTangentType();
         
         if (tangenttype == BEZIER)
             strategy = Tangent.bezierStrategy();
         else {
             float f = factorView.demandFloat();
             
             strategy = Tangent.chordStrategy(f);
         }
         
         shape = new AutomaticCurve(points, strategy, mode, rule);
    }
    
    paintShape();
}

As you can see, this method calls various helper methods that extract the current user settings from the GUI. In the case of a cubic, the AutomaticCurve constructor requires an extra parameter that provides the tangent strategy. This strategy encapsulates the algorithm that computes the control points from the vertex points. The two strategies built into JPT are found in class Tangent as is seen in the above code.

The main constructor for an AutomaticCurve is similar to that for a PolygonShape except that it has two extra parameters, an array to specify end tangents if the curve is open and the tangent strategy parameter:

public AutomaticCurve
    (float[][]        vertex,
     float[][]        endTangent,
     Tangent.Strategy tangentstrategy,
     ClosureMode      closuremode,
     WindingRule      windingrule)

The endTangent parameter allows one to specify the end tangents if the cubic curve is open via a float[2][2]. The usage of this parameter is more subtle and you may safely omit it for now. Thus, the constructor we recommend is:

public AutomaticCurve
    (float[][]        vertex,
     Tangent.Strategy tangentstrategy,
     ClosureMode      closuremode,
     WindingRule      windingrule)

Here is a little puzzle related to the star. Can you make the star shape by drawing only the outer outline? If you think about it, you will need 10 data points not 5 since you need to explicitly know the intersection points of the 5 star edges. You need some math to actually figure out the coordinates of the intersection points. It is also necessary to get the 10 points into a float array in the correct order. See if you can do it!

Back to the Top

Down to the Bottom

11/13/06: Concentration Game

The Concentration Game was originally posted on the JPT 2.3.5 site about two years ago. The code here has been carefully refactored to improve its structure and readability.

In the Concentration Game, the user is presented with a square array of hidden tiles. Upon clicking on a tile, its image is revealed. Upon clicking on a second tile, its image is also revealed. If the two tiles match, then they will continue to be visible. If they do not match, then, on the next click, they will once again be hidden. By remembering the location of tiles already shown, the user can make matches more easily as the game proceeds. The goal is to match tiles with the fewest number of guesses.

In this implementation of Concentration, the user is first presented with a panel that allows a choice of settings.

Snapshot of the concentration settings panel

Using the settings panel, the user may select the choice of images (shapes, photos, letters of the alphabet, or numbers). The user is also given 4 choices of grid size (3-by-3, 4-by-4, 5-by-5, or 6-by-6). The limit of 6-by-6 is based primarily on limitations of screen real estate.

Here are screen snapshots (at 50% of full size) showing samples of the shapes and samples of the photos.

Concentration snapshot with shapes            Concentration snapshot with photos

When the images are letters or numbers, the game appears to be more difficult since the memorization is more purely intellectual and has less of a visual component.

The concentration game is available both as an application and as an applet.

Access to the Concentration Applet.

Most of the code for the Concentration Game is the same for the application and the applet. A notable difference is the code for obtaining the images. The application uses images in a directory on the local disk whereas the applet uses web images. Since it is possible that the images may fail to load, the program will revert to shapes if images are not available. We now provide the Java code.

Code Common to the Application and the Applet

The Java file ConcentrationSettings.java

This class manages the choice of user settings and also gathers all images once and for all so that any version of the Concentration Game may be easily created.

The Java file ConcentrationGame.java

This class selects the images that will be shown in the tiles and arranges that each image occurs an even number of times so that matches are always possible. This class also creates the GUI for the game.

The Java file GameTile.java

This class creates a special tile that can selectively show its contents and can control whether or not the mouse is active in the tile.

The Java file GameShapes.java

This class creates the images corresponding to filled shapes.

The Java file GameText.java

This class creates the images corresponding to text, that is, the images for letters and numbers.

Application Specific Code

The Java file GameImages.java for the application.

This class loads the photos from a directory on the local disk for use in the application.

The photos should be 100-by-100 pixels since only that much of each photo will be displayed.

Here is a zip file with the photos: images.zip.

The same photos are in fact used on the web site for the applet version of the program.

Applet Specific Code

The Java file GameImages.java for the applet

This class loads the photos from a web directory for use in the applet.

The Java file ConcentrationApplet.java

This class launches an applet with the ConcentrationSettings as its GUI.

Notes

There are two files with the same name, GameImages.java, one for the application and one for the applet. The class ConcentrationSettings makes a static reference to the class GameImages so by substituting a different file for the application and for the applet we can easily arrange that the photos come from different sources.

Back to the Top

Down to the Bottom

11/17/06: Random Shape Demos

Random Shape Demo screen snapshot

In class, on November 16, 2006, in response to a student question, I developed two versions of a program that add random circles to a graphics pane each time a button is clicked. Each program installs mouse actions that enable the circles to be dragged with the mouse. When a circle is clicked it moves to the topmost position so it is above all other circles. To the user, both programs appear to have the same GUI and the same behavior.

We will provide a link to the source of each program and then describe briefy the particular features.

The Java file RandomShapeClass1.java

This program uses BufferedPanel to create its graphics pane. Since a BufferedPanel has a built-in PaintableSequence is is easy to add individual circles as ShapePaintable objects to the sequence. Furthermore, a BufferedPanel has a built-in set of mouse actions that will allow the user to drag the items in the sequence with the mouse. Thus, to get this mouse behavior requires a single line of code. In total, except for import statements, the entire program is one screen of code.

The Java file RandomShapeClass2.java

This program manually constructs a graphics pane using a PaintableSequence that is placed in a Tile that is in turn placed in a PaintableComponent. The default bounds of the Tile are set at 500-by-500 so that it maintains its size regardless of what is in the internal PaintableSequence. In comparison with the first version of the program, there is only a tiny change in the code to add a new circle. Where the work comes in is with the mouse actions since these are not built-in. We must define methods to implement the mouse press and drag behavior, mouse action objects to encapsulate these methods as objects, and installation code to attach the mouse actions to the paintable component wrapper. In total, except for import statements, the entire program is two and a half screens of code. You may view the extra code as revealing the kind of code that is built into BufferedPanel and available automatically.

Back to the Top

Down to the Bottom

11/17/06: Dice in Java and Scheme

In Exercises 1, I asked you to build a small demo program that randomly tosses a pair of dice. Here is a screen snapshot of my solution to this problem and its source code.

Dice in Java

The Java file Dice.java

Last evening, Tim Klopotoski sent me an interesting program in Scheme that tosses dice. His words: “Very short. Very beautiful.” Tim explained to me a fact that I considered astounding: Scheme can embed image files into Scheme code. There is no need to reference images via file names or web links. Tim's GUI building is a tour-de-force since he, in effect, manually creates a button and tests for a mouse click. Bravo.

Dice in Scheme

The Scheme file dice_tosser.scm

Back to the Top

Down to the Bottom

11/20/06: Spinning Animation

The screen shapshots below show the control panel for launching spinning animations and one example of a spinning animation.

Spinning methods buttons            Spinning animation with star (7,3)

The Java file SpinningMethods.java

Class SpinningMethods launches several different spinning animation examples. The user can in fact have a number of such animations running at once within the limits of available processor cycles.

The Java file SpinningAnimation.java

Class SpinningAnimation defines a panel that can spin an arbitrary Paintable object. The class is similar to BallAnimation above but is more general since it accepts an arbitrary paintable. Furthermore, the rotation may be reversed instantly with the click of a radio button.

The Java file RegularShape.java

Class RegularShape has static methods to construct a regular polygon shape and regular star shape.

Star Geometry and Trigonometry

Let us explain in detail the geometry and trigonometry that is involved in the construction of the star shapes. Each star is characterized by its center (x,y), its outer radius r, the number of outer vertices, and the jump between vertices that determines the specific star shape. In the snapshot below, vertices equals 7 and jump equals 3 so this would be described as a 7,3 star. Our goal is to draw the star as an outline so you can see that we not only need the outer vertices we also need an equal number of inner vertices. The inner vertices are determined by where the lines joining the outer vertices would cross. We have drawn a dashed line to suggest one such line joining a pair of outer vertices separated by the jump.

Diagram illustrating star geometry and trigonometry

In the diagram, C is the center of the star, A is the topmost outer vertex, B is the next inner vertex clockwise from A, and Z is the outer vertex jump steps from A. We are given the outer radius r. We can compute B if we can compute the inner radius s from C to B. We will do this using geometry and trigonometry.

First, the total number of vertices (outer and inner) is V where:

    V = 2vertices

Then, the angle C, in the triangle CAB is given by:

    C = 360.0 / V = 180.0 / vertices

Next, consider the large isosceles triange CAZ. The large angle at C in this triangle is given by:

    C_Large = 360.0jump / vertices

Since CAZ is isosceles, we can compute the angle at A as:

    A = (180.0 - C_Large) / 2 = 90.0 - 180.0jump / vertices

Then, using triangle CAB, we can compute the angle B as:

    B = 180.0 - A - C

Now, using the “Law of Sines” from trigonometry, we have the equation:

    r / sindeg(B) = s / sindeg(A)

or

    s = rsindeg(A) / sindeg(B)

This is the formula used to compute the star shape in the Java class RegularShape.java.

Aside: This is yet another example of why students of computing should know some mathematics. Mathematicians have spent thousands of years discovering some nifty things that are quite useful in computing.

Back to the Top

Down to the Bottom

Added 12/1/06: Spinning Animation Applet

Access to the Spinning Animation Applet

The Java file SpinningAnimationApplet.java

Back to the Top

Down to the Bottom

3/2/07: Functions Plotter

Access to the Functions Plotter Applet.

Access to the Directions and Discussion for the Functions Plotter Applet.

Back to the Top

Down to the Bottom

3/25/07: JPT Image IO

The class JPTImageIO builds on the methods introduced in Java 5.0 in the class ImageIO. See the javadocs for that class for more details.

The class provides a static method to write images based on the following entities:

The entity RenderedImage that is used in the class ImageIO is also supported.

The class has useful helper methods that are public.

In Java 5.0, the following write format names are supported:

Experiments show that writing images using bmp or png formats produces high quality images but that writing images with jpg produces images of low quality with many artifacts.

Below is an example of a star image on a red background that was saved using bmp:

Star using bmp

Below is an example of a star image on a red background that was saved using jpg:

Star using jpg

It is evident that the jpg image produced by the algorithms supplied by Java 5.0 is far inferior to the bmp image from the same source. The source in this case was an image painted in a BufferedPanel.

The Java file: JPTImageIO.java

The Java test file: Methods.java

The Java helper file that defines the star shape: RegularShape.java

Back to the Top

Down to the Bottom

4/1/07: Keys, Animation, Threads

On November 18, 2005, we posted a demo that illustrated the tracking of key press-release states and the use of such tracking for animation. This demo utilized several helper classes that were later introduced into JPT during Summer 2006. Below we show a screen snapshot of the demo and then give the slightly revised source code that uses the JPT classes.

KeyTrackerDemo snapshot

The Java file: KeyTrackerDemo.java

This demo uses two separate threads in addition to the standard “GUI thread”.

The first thread examines the state of the five keys of interest (up arrow, down arrow, left arrow, right arrow, and shift) and echoes this state into a small paintable that is shaped as a large plus sign with 5 tiles. When the shift key is pressed, the center tile is highlighted. When an arrow key is pressed, the corresponding tile (N, S, W, E) is highlighted. The purpose of this thread is to show whether or not a key press or release has been detected by the software.

The second thread moves the paintable square if at least one arrow key is pressed. The purpose of the second thread is to have a longer delay if the paintable is being moved so that the movement delay is not forced to be the same as the much smaller delay that is used to signal detection of a key press or release. This design keeps the square from moving too quickly.

This demo illustrates the fact that one may launch multiple threads besides the default “GUI thread”.

In the demo above, the two threads run for the duration of the program. The methods class below, illustrates a short-term thread that runs only as long as is needed to animate a ball moving up and then moving down.

The Java test file: Methods.java

Back to the Top

Down to the Bottom

4/1/07: Counter Animation

The Counter Animation in similar to the Ball Animation but increments numbers in a TextPaintable instead of moving a shape. Therefore, we will just provide access to the applet and the source.

Access to the Counter Applet.

The Java file: Counter.java

The Java file: CounterApplet.java

Back to the Top

Down to the Bottom

4/5/07: Stack Trace, String Viewer, Bad GUI Applets

The goal of this example is to provide a utility that will return the stack trace associated with a Throwable object, normally, an Exception object. This utility is defined in the class:

The Java file: StackTrace.java

Of course, a stack trace is usually multiple lines of text, some of which are quite wide. Hence it is convenient to have additional utilities that will display a string in a scroll pane that is in turn placed into a frame or into an OK dialog box. These are provided in the class:

The Java file: StringViewer.java

The sample test application does nothing but throw an exception:

The Java file: BadGUI.java

This bad GUI application is in turn called by an applet that has extra code to trap and display the exception stack trace.

The Java file: BadGUIApplet.java

This is a model for how to set up an applet if you wish to catch and display exceptions that occur as the GUI is being constructed.

Here is the access to the BadGUIApplet. You will see that an exception is thrown and that the message is displayed in a dialog box.

Here is the heart of the html code for the BadGUIApplet web page. It is parallel to the applet code for all other applets on this site.

<h1>
Bad GUI Applet
</h1>

<h4>
The applet on this page intentionally throws an exception in
the course of building its GUI.  The purpose is to demonstrate
the technique for viewing the exception stack trace in an OK
dialog box.
</h4>

<p class="centered">
<applet
codebase="./bin/"
code="BadGUIApplet.class"
archive="http://www.ccs.neu.edu/jpt/archive/2.5.0/lib/jpt.jar"
width="100"
height="100"
>
</applet>
</p>

Back to the Top

Down to the Bottom

4/12/07: Ball Animation with SimpleThreadedAction

In earlier examples with animation and threads, it was necessary to build a SimpleAction and pass it to a wrapper class ThreadedAction in order to force the action to execute in a separate thread. As we have seen, the separate thread is the key to running the animation with appropriate pauses while the GUI remains alive.

Recently, my mental light bulb went on and I realized that it would be very convenient to build the action and make it run in a separate thread all in one step. This was easy to do and is available in the class below. The class SimpleThreadedAction will become part of JPT in the next release.

The Java file: SimpleThreadedAction.java

Here is the revised BallAnimation class.

The Java file: BallAnimation.java

In the prior version of BallAnimation, the animation action was set up as follows:

    private ThreadedAction runAction =
        new ThreadedAction
            (new SimpleAction("Run Animation") {
                public void perform()
                { runAnimation(); }
    });

This code is now simplified to:

    private SimpleThreadedAction runAction =
        new SimpleThreadedAction("Run Animation") {
            public void perform()
                { runAnimation(); }
    };

Although, this is only slightly shorter, it is conceptually much simpler.

The applet code is in fact the same as before.

The Java file: BallAnimationApplet.java

Here is access to the applet: Ball Animation Applet.

Back to the Top

Down to the Bottom

4/12/07: Ship: Graphics Composite

A key question in building graphics entities for more complex programs such as games is how to build composites, that is, entities that are made up two or more fragments that build the entity. Here is a trivial example of what we mean, a space ship with the rocket thrust coming from its rear.

Space Ship Snapshot

Certainly, this is the world's most simple-minded space ship but it is adequate to illustrate the idea of a composite of two or more fragments, in this case, the silver triangle that represents the space ship body and the red thrust rectangle that acts as a tail.

The natural JPT class to use to build a composite is PaintableSequence since it can collect one or more Paintable fragments that may be drawn in the order specified during construction. The class Ship1 given below is a derived class of PaintableSequence. It uses the constructor to put together the fragments that combine to make the space ship.

The Java file: Ship1.java

From the point of view of abstraction, however, the above solution is a hack since we do not want to view a ship as a PaintableSequence to which other random fragments may be added. We would prefer to build the ship internally and force the outside world to see it simply as a Paintable entity. This can be accomplished using the class PaintableSequenceComposite. This is done in the class Ship2 given below.

The Java file: Ship2.java

The key to this design is that the class Ship2 can access an internal PaintableSequence via a protected get method but callers in the outside world do not have access to this sequence. This makes the Ship2 object an object that uses parts in its construction but whose parts cannot be seen from the outside.

Here is the test class. To distinguish the ships built from each class, the Ship1 object is rotated 30 degrees and the Ship2 object is rotated 60 degrees. In each class, the turn method illustrates how to add simple extra functionality.

The Java test file: Methods.java

Back to the Top

Down to the Bottom

5/2/07: LayeredComponent

A significant annoyance in classic Java is that the background of a component or a panel as set via setBackground can only be a Color. It would be much more convenient if the background could consist of images, shapes, text, paints, etc. This problem is solved via a new class LayeredComponent that will be incorporated in the next release of JPT.

A LayeredComponent takes the following ingredients:

As you can see, LayeredComponent is general enough to provide for both background objects, background paint, or both. Below is the source:

The Java file: LayeredComponent.java

Here are two screen snapshots from test code.

Test background at 50% opacity Test background at 100% opacity
Background at 50% opacity Background at 100% opacity

The test code requires 2 images, one of apples in the foreground and one of a tree in the background. You will notice 2 controls that allow you to vary how the background is rendered. The slider allow the user to control the opacity. The radio buttons allow the user to decide whether or not to center the background object relative to the foreground. This allows easy experimentation with the LayeredComponent widget. In practice, of course, the designer would normally make these settings.

During testing, we experimented with placing the slider and radio buttons within the layered component and setting their own backround to a transparent color. However, when a user interacts with such controls, Java makes subtle changes in rendering that produce strange artifacts because Java assumes that that the control background is opaque and that rendering shortcuts may be taken. This is therefore a limitation on the usage of LayeredComponent.

Below is the test code:

The Java test file: TestLayeredComponent.java

Since the test process requires images (which are kept in an images folder), we provide all of the pieces in a zip file.

The complete zip file: LayeredComponent.zip

Back to the Top