Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Swing

An Introduction to the Java 2D API

4.50/5 (5 votes)
11 Mar 2009CPOL6 min read 36.4K  
An article for the student of Java GUI programming.

An Introduction to the Java 2D API

This paper will focus on the Java 2D API. Rather than jump straight into that API, this paper will begin with a few basics on Java GUI programming and applet coding, and then go into further details about the Java 2D API. In Java, graphics began with AWT. The Abstract Windows Toolkit (AWT) has been, and still is, used in the Java language to create graphical user interface programs which function as either stand-alone applications or applets that load when the browser loads. After the introduction of AWT, Sun, and Netscape jointly contrived and developed the Swing toolkit. Swing has proved to be a more powerful GUI mechanism for applications that use "widgets", or components. Here is some sample code:

Java
import javax.swing.*;
public class CheckGrade {
 public static void main(String[]  args) {
   String strScore = JOptionPane.showInputDialog(null, "Enter your grade");
   int score = Integer.parseInt(strScore);
   String comment;
   if ( score >= 60) {
     comment = "You have passed";
   }else{
     comment = "You have failed";
   }
   JOptionPane.showMessageDialog(null, comment);
 }
}

Compiling it:

C:\Sun\SDK\JDK\bin>javac.exe CheckGrade.java

C:\Sun\SDK\JDK\bin>java CheckGrade

1.JPG

2.JPG

Almost all uses of the JOptionPane class are one-line calls to one of the static showXxxDialog methods shown below:

  • showConfirmDialog asks a confirmation question, for yes/no/cancel.
  • showInputDialog prompts for some input.
  • showMessageDialog tells the user about something that has happened.
  • showOptionDialog is the grand unification of the above three.

Code explanation: The JVM reads each data type in String format, so if we are to enter a primitive integer type, then we have to use a format like this: int x = Integer.parseInt(“Some string”) because the entered value is an integer, but will be interpreted as a string. We thus change the string to an integer. Here, Integer is the name of a class defined in the built-in java.lang package and parseInt() is a method of the Integer class that converts a String to an Integer. The purpose of the if statement is to make a decision, and execute parts of your program depending on a boolean true/false.

The Basics of Applets

Applets do not have a main() method as a starting point of code execution. Nor are they interpreted by the Java compiler. They are initialized by the init() method. As with any Java program, the name of the file is the name of the class that you are declaring, except that this declared class extends the Applet class that is defined in the java.awt package. Below is some basic (and perhaps outdated) applet code. Note that the system calls the paint() method. Also note that we are drawing lines, and to draw those lines, we need to iterate the variable i that is part of the dimensions of the applet:

Java
import java.applet.*;
import java.awt.*;
public class CreateLines extends Applet {
 int width, height;
 public void init() {
      width = getSize().width;
      height = getSize().height;
      setBackground( Color.black);
 }
 public void paint( Graphics g ) {
      g.setColor( Color.red );
      for ( int i = 0; i < 10; ++i ) {
         g.drawLine( width, height, i * width / 10, 0 );
      }
 }
}

This code must be compiled by the javac.exe compiler in order to create a class file:

C:\Sun\SDK\JDK\bin>javac.exe CreateLines.java 

3.JPG

C:\Sun\SDK\JDK\bin> type con > somefile.html

The output:

HTML
<html> 
<body>
<applet code="CreateLines.class" width = 400 height = 400></applet>
</body>
<html>

Now, type somefile.html.

To see the strength of the applet, the writer of this paper refers you to http://www.echoecho.com. This web page has a stunning applet with its corresponding class file for download. Just make sure that you save the image file, the HTML file, and the class file in the same working directory.

An Overview of the Java 2D API

In Java 1.2 and up, the paintComponent method is supplied with a Graphics2D object (a subclass of Graphics), which contains a much richer set of drawing operations. It includes pen widths, dashed lines, image and gradient color fill patterns, the use of arbitrary local fonts, a floating point coordinate system, and a number of coordinate transformation operations. The Java 2D API provides advanced two-dimensional graphics capabilities for programmers. The API includes features for processing line art, text, and images in the packages java.awt, java.awt.image, java.awt.color, java.awt.font, java.awt.geom, java.awt.print, and java.awt.image.renderable. Drawing with the Java 2D API requires a Graphics2D reference (package java.awt). Graphics2D is an abstract subclass of the Graphics class, so it has all the graphics capabilities mentioned. In fact, the actual object used to draw in every paintComponent method is an instance of a subclass of Graphics2D that is passed to the method paintComponent and accessed via the super class Graphics. To access Graphics2D capabilities, we must cast the Graphics reference (g) passed to paintComponent into a Graphics2D reference, with a statement such as:

Java
//Cast the Graphics object to a Graphics2D object
public void paintComponent(Graphics g) {
  super.paintComponent(g);  
  Graphics2D g2d = (Graphics2D)g;
  g2d.doSomework(...);
  ...
}

Create a Shape object

  • Rectangle2D.Double rect = ...;
  • Ellipse2D.Double ellipse = ...;
  • Polygon poly = ...;
  • GeneralPath path = ...;
  • ...

Draw an outlined or solid version of the Shape:

  • g2d.draw(someShape);
  • g2d.fill(someShape);

Modify the drawing parameters using some of these methods.

  • g2d.setPaint(fillColorOrPattern);
  • g2d.setStroke(penThicknessOrPattern);
  • g2d.setComposite(someAlphaComposite);
  • g2d.setFont(someFont);
  • g2d.translate(...);
  • g2d.rotate(...);
  • g2d.scale(...);
  • g2d.shear(...);
  • g2d.setTransform(someAffineTransform);Rectangle2D.Double rect = ...;
  • Ellipse2D.Double ellipse = ...;
  • Polygon poly = ...;
  • GeneralPath path = ...;

Draw an outlined or solid version of the Shape:

  • g2d.draw(someShape);
  • g2d.fill(someShape);

Modify the drawing parameters:

  • g2d.setPaint(fillColorOrPattern);
  • g2d.setStroke(penThicknessOrPattern);
  • g2d.setComposite(someAlphaComposite);
  • g2d.setFont(someFont);
  • g2d.translate(...);
  • g2d.rotate(...);
  • g2d.scale(...);
  • g2d.shear(...);
  • g2d.setTransform(someAffineTransform);

This example is going to draw an ellipse inside a window. The darkened ellipse is contained inside a window, or a container, the top-most of which is called JFrame. Below is the main file, and notice that contained in the main() method is an undefined class called OSTools. The Example.java file is therefore dependent on the class file OSTools.java. Looking at OSTools.java tells us that OSTools is dependent on the ExitListener.java file. OSTools.java and ExitListener.java are only compiled into byte code for their class files to function as a “blueprint” for the application. Here is the main file, Example.java:

Java
import javax.swing.*;        
import java.awt.*;           
import java.awt.geom.*;      
public class Example extends JPanel {
  private Ellipse2D.Double circle =
    new Ellipse2D.Double(10, 10, 350, 350);
  private Rectangle2D.Double square =
    new Rectangle2D.Double(10, 10, 350, 350);
    public void paintComponent(Graphics g) {    
    clear(g);
    Graphics2D g2d = (Graphics2D)g;            
    g2d.fill(circle);
    g2d.draw(square);
  }
    protected void clear(Graphics g) {
    super.paintComponent(g);
  }
    protected Ellipse2D.Double getCircle() {
    return(circle);
  }
   public static void main(String[] args) {
    OSTools.openInJFrame(new Example(), 380, 400);
  }
}

We see the OSTools class and know that it is not defined in any imported package. This is a class file that must have its source code compiled into a class file. Recall that the top-most level container (or window) in Swing is the JFrame. The JFrame, however, would be just a blank user interface if we did not add components onto it. JPanel is called the content pane where we put the components onto our window.

Java
import java.awt.*;
public class OSTools {
 public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height,
                                    String title,
                                    Color bgColor) {
    JFrame frame = new JFrame(title);
    frame.setBackground(bgColor);
    content.setBackground(bgColor);
    frame.setSize(width, height);
    frame.setContentPane(content);
    frame.addWindowListener(new ExitListener());
    frame.setVisible(true);
    return(frame);
  }
  public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height,
                                    String title) {
    return(openInJFrame(content, width, height, title, Color.white));
  }

 public static JFrame openInJFrame(Container content,
                                    int width,
                                    int height) {
    return(openInJFrame(content, width, height,
                        content.getClass().getName(),
                        Color.white));
  }
}

Notice that a new ExitListener object was created, which means we have to define the class:

Java
import java.awt.*;
import java.awt.event.*;
public class ExitListener extends WindowAdapter {
  public void windowClosing(WindowEvent event) {
    System.exit(0);
  }
}

6.JPG

The compilation of the class files and the main file produces this image:

5.JPG

Transparent drawing

Java 2D permits you to assign transparency (alpha) values to drawing operations so that the underlying graphics partially shows through when you draw shapes or images. You set a transparency by creating an AlphaComposite object and then passing the AlphaComposite object to the setComposite method of the Graphics2D object. You create an AlphaComposite by calling AlphaComposite.getInstance. The AlphaComposite API provides eight built-in mixing rules, but the one normally used for drawing with transparency settings is AlphaComposite.SRC_OVER, a source over destination mixing rule that places the source (shape) over the destination (background). Alpha values can range from 0.0f (completely transparent) to 1.0f (completely opaque). Partially overlapping is a red square drawn with an initial alpha value of 0.0f at the far left. The red square is repeatedly drawn at new locations across the panel with alpha values that gradually increase by a step size of 0.1f until, finally, total opaqueness is reached at the far right with an alpha value of 1.0f.

Here is some code that demonstrates this example. Again, this main file is dependent on the OSTools.java class file:

Java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Transparent extends JPanel {
    private static int gap=10, width=60, offset=20,
    deltaX=gap+width+offset;
    private Rectangle
    blueSquare = new Rectangle(gap+offset, gap+offset, width,
    width),
    redSquare = new Rectangle(gap, gap, width, width);
    
    private AlphaComposite makeComposite(float alpha) {
        int type = AlphaComposite.SRC_OVER;
        return(AlphaComposite.getInstance(type, alpha));
    }

    private void drawSquares(Graphics2D g2d, float alpha) {
        Composite originalComposite = g2d.getComposite();
        g2d.setPaint(Color.blue);
        g2d.fill(blueSquare);
        g2d.setComposite(makeComposite(alpha));
        g2d.setPaint(Color.red);
        g2d.fill(redSquare);
        g2d.setComposite(originalComposite);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        for(int i=0; i<11; i++) {
            drawSquares(g2d, i*0.1F);
            g2d.translate(deltaX, 0);
        }
    }

    public static void main(String[] args) {
        String title = "Transparency example: alpha of the top " +
        "(red) square ranges from 0.0 at the left " +
        "to 1.0 at the right. Bottom (blue) square " +
        "is opaque.";
        OSTools.openInJFrame(new Transparent(),
        11*deltaX + 2*gap,
        deltaX + 3*gap,
        title, Color.lightGray);
     }
}

Image 6

Suggested reading

  • Introduction to Programming using Java, by David J. Eck
  • Thinking in Java, by Bruce Eckel

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)