From late 1997 to late 2004, I developed and ran a very nice Java course. Took it all round the world, in fact.
It's still available…and still the best Java course out there, IMHO (and I have given quite a few from several other [major] vendors in addition to my own).
One of the exercises that that participants seemed to enjoy was to take an applet not to dissimilar from the Scribble applet published in David Flanagan's Java in a Nutshell and modify it so that the drawing persevered through
screen redraws.
This helped the participants get their head around anonymous inner classes and the applet lifecycle callbacks and also gave them a chance to play with the List collection interface/classes.
Time moves on and we now have Groovy's SwingBuilder and the new JavaFX technology promoted by Sun.
Prompted by the negative press that JavaFX has received, postings such as this and the speed increases of the "consumer JRE", together with the fact that it is now
bundled into Netbeans 6.5.1 (making it easy to get hold of and play with; not sure why it is currently missing in action for 6.7m3) I decided to see how the 'newcomers' stacked up.
The examples aren't completely identical (one is an applet, while the others are JFrames, for example) but this is still a nice 'feel' exercise.
I am reminded of the Evolution of a Programmer joke…
Here goes…
=== Java (in homage to Java in a Nutshell, Second Edition)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PerseveringScribbleCollections extends java.applet.Applet
{
int last_x = 0;
int last_y = 0;
List model = new ArrayList ();
public void init ()
{
addMouseListener
(
new MouseAdapter ()
{
public void mousePressed (MouseEvent e)
{
last_x = e.getX ();
last_y = e.getY ();
}
}
);
addMouseMotionListener
(
new MouseMotionAdapter ()
{
public void mouseDragged (MouseEvent e)
{
Graphics g = getGraphics ();
int x = e.getX ();
int y = e.getY ();
g.setColor (Color.black);
DrawLine d = new DrawLine (last_x, last_y, x, y);
model.add (d);
d.paint (g);
last_x = x;
last_y = y;
}
}
);
}
public void paint (Graphics g)
{
ListIterator l = model.listIterator ();
while (l.hasNext ())
{
((DrawLine) l.next ()).paint (g);
}
}
}
class DrawLine
{
private int x0;
private int y0;
private int x1;
private int y1;
public DrawLine (int x0, int y0, int x1, int y1)
{
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
}
public void paint (Graphics g)
{
g.drawLine (x0, y0, x1, y1);
}
}
=== Groovy (based on the Java version, above. All my own work ;=))
import javax.swing.WindowConstants as WC
import groovy.swing.SwingBuilder
import java.awt.Color
import java.awt.Graphics
import javax.swing.JPanel
def list = []
def last_x = 0
def last_y = 0
SwingBuilder.build {
frame(title: 'Groovy Scribble',
size: [600, 400],
show: true,
pack: false,
resizable: false,
defaultCloseOperation: WC.EXIT_ON_CLOSE) {
widget(new Scribble(list: list),
mousePressed: {e ->
(last_x, last_y) = [e.x, e.y]
},
mouseDragged: {e ->
(x, y) = [e.x, e.y]
def d = new DrawLine(x0: last_x, y0: last_y, x1: x, y1: y)
d.paint(e.component.graphics)
list << d
(last_x, last_y) = [x, y]
}
)
}
}
class Scribble extends JPanel {
def list = []
public void paint(Graphics g) {
list.each { it.paint(g) }
}
}
class DrawLine {
def x0
def y0
def x1
def y1
public void paint(Graphics g) {
g.setColor(Color.black);
g.drawLine(x0, y0, x1, y1);
}
}
=== JavaFX (adapted from Planet JFX)
package au.com.transentia.scribble.javafx;
import java.lang.System;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.*;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
def w = 600;
def h = 400;
class Scribble extends CustomNode {
var polyline: Polyline;
public override function create(): Node {
var group: Group = Group{
onMousePressed: function (e: MouseEvent) {
polyline = Polyline{ points: [e.sceneX, e.sceneY] };
insert polyline into group.content ;
}
onMouseDragged: function (e: MouseEvent) {
insert [e.sceneX, e.sceneY] into polyline.points;
}
content: Rectangle {
width: w
height: h
fill: Color {opacity: 0}
}
}
return group;
}
}
Stage {
onClose: function(): Void {
System.exit(0);
}
title: "JavaFX Scribble"
width: w
height: h
visible: true
resizable: false
scene: Scene {
content: [Scribble{}]
}
}
I'm not going to draw any conclusion…not one. Nope, not one. "Left as an exercise for the reader", that sort of thing applies here…
I had fun and each example is interesting, in its own way.
Enjoy.