/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* JavaWorld Library, Copyright 2011 Bryan Chadwick *
* *
* FILE: ./imagetutor/package-info.java *
* *
* This file is part of JavaWorld. *
* *
* JavaWorld is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation, either version *
* 3 of the License, or (at your option) any later version. *
* *
* JavaWorld is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with JavaWorld. If not, see
We've been developing a new Java library,
coined JavaWorld
, that supports the development of
visual and interactive programs in the style of
DrRacket's
2htdp/universe
module/teachpack, with an object-oriented twist.
This tutorial will walk you through the setup and some of the
features of the JavaWorld
.
Jars
First, you need the JavaWorld.jar, which contains the Image and World packages/libraries. Make sure the Jar is part of your build-path in the Project you want to work from.
The important parts of the documentation for JavaWorld are Images and Worlds. Though the entire documentation can be found here.
When necessary we will reference specific pages. As you become a more accomplished programmer, more and more of the library will make sense, and you'll be able to write more complex programs. Feel free to poke around, but don't get lost in all the details too quickly. We'll guide you through the basics, then you can explore more on your own as you get more experience.
The JavaWorld library contains lots of Java classes to help with the creation of graphical programs. Here's a review of the important ones.Images
All of theImage
classes can be used (assuming the libraries are setup appropriately) simply by importing them:The classes are similar in design to the Racket 2htdp/image module that you may already be familiar with.import image.*;
Classes and Methods
Creating images is as easy as creating instances of classes. There is a full list with examples here. But a few of the important ones are discussed below.Class Constructors
EmptyScene
(int width, int height) Circle
(int radius, String mode, String color) Rectangle
(int width, int height, String mode, String color) Text
(String text, int size, String color) Star
(int radius, int points, String mode, String color) Overlay
(Image top, Image bot) OverlayXY
(Image top, int x, int y, Image bot) See the next section or the image documentation for more descriptions and examples.Methods
Scenes
Scene placeImage(Image image, int x, int y)
Scene addLine(int fromX, int fromY, int toX, int toY, String color)
Images
Image overlay(Image top)
Image overlayxy(Image top, int x, int y)
World.display()
Images are pretty easy to create and compose, but in order to display them we need something a bit more complicated. To see the image(s) you create, we provide a method that pops up a window to display an Image (or a Scene).
Simple Images/Scenes
To display our images, we create a simple class that creates a Scene and displays it from within a main method, though this could also be done from within a testing framework (I.e., the NU Tester, or JUnit). Here's an initial example, Example1, that uses Circle, Square, and OverlayXY to create a Scene. The Scene is then displayed when the main method is run.import image.*; import world.*; public class Example1{ Example1(){} Scene mt = new EmptyScene(100, 100); Image circ = new Circle(20, "outline", "blue"); Image sqr = new Square(40, "solid", "palegreen"); Scene scn = mt.placeImage(new OverlayXY(circ, -20, 20, sqr), 50, 50); public static void main(String[] args){ World.display(new Example1().scn); } }Running this example results in a window similar to the following:
The World.display to show the constructed image/scene after we've created an instance of Example1. World.display returns a value of true once the popup window is closed.
Natural-Number Recursion
Of course, we're not limited to hand constructed Scenes since we know how to use recursion over the natural numbers. Example2 implements a recursive method, stars, that builds a Scene. Our base-case returns the EmptyScene, and our recursive case places (placeImage) a Star of the given size in the Scene returned by the recursive call.public class Example2{ Example2(){} // Create a Scene with nested stars of decreasing size Scene stars(int size){ if(size <= 4){ return new EmptyScene(200, 200); }else{ return this.stars(size-15) .placeImage(new Star(size, "outline", "red"), 100, 100); } } Scene scn = this.stars(100); public static void main(String[] args){ World.display(new Example2().scn); } }We start with a size of 100, and display the result. Running this example results in a window similar to the following:
Structural Recursion
As you remember (hopefully), natural-number recursion is just a special case of structural recursion (which, in turn, is just a special case of what HtDP calls generative recursion).As an example of a recursive structure, below we define an interface and classes that together represent a chain of arbitrary length. Link and End implement IChain, which contains a single method header. What's important for this example is that we can place an image of an IChain into a given Scene.
// Represents a Chain interface IChain{ // Place this IChain into the given Scene public Scene place(int x, Scene scn); } // Represents a Link in a Chain class Link implements IChain{ IChain next; Link(IChain next){ this.next = next; } // Place this Link into the given Scene public Scene place(int x, Scene scn){ return this.next.place(x+25, scn) .placeImage(new Overlay(new Ellipse(28, 13, "outline", "gray"), new Ellipse(30, 15, "outline", "black")), x, 50); } } // Represents the end of a Chain class End implements IChain{ End(){} // The end of the chain, return the Scene public Scene place(int x, Scene scn){ return scn; } }Each of the classes implements the method, Scene place(int, Scene), which returns the appropriate scene. For the End of the IChain we simply return the given Scene. For a Link we place an Ellipse in the Scene returned by the recursive call on the next IChain.
Now all we need to do is create an examples class that creates an IChain instance and has a test method that displays the IChain after placing it into the EmptyScene.
public class Example3{ Example3(){} IChain ch = new Link(new Link(new Link( new Link(new Link(new Link(new End())))))); Scene scn = this.ch.place(40, new EmptyScene(200, 100)); public static void main(String[] args){ World.display(new Example3().scn); } }Running this example results in a window similar to the following:
If this leaves you craving more, have a look through the Image and World documentation.