Purpose: We will work through a program that draws curves.
import java.awt.*; import java.awt.geom.*; import javax.swing.JFrame; import javax.swing.JPanel; public class DrawingDemo extends JPanel { /** Default constructor. */ public DrawingDemo() { this.setBackground(Color.WHITE); // Make the background color white } /** This is called when we need to draw something. */ @Override public void paintComponent(Graphics gfx) { // This stuff is standard: super.paintComponent(gfx); // Paint the component (such as the background). Graphics2D g = (Graphics2D) gfx; // Better to draw with a Graphics2D object. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Anti-aliasing looks pretty! // We are drawing to a rectangle representing the visible portion of the screen. // The upper left corner of the rectangle has coordinates (0,0). // The lower right corner is (getWidth(), getHeight()). // Edit what is below to create your own drawing! // Draw a large translucent line segment joining (0,0) to (W,H). Line2D line=new Line2D.Double(0,0, getWidth(), getHeight()); g.setColor(new Color(0,0,0,64)); // Draw in black, but translucent! g.setStroke(new BasicStroke(20)); g.draw(line); } /** Create a window and put our panel on display inside it. */ public static void main(String[] args) { JFrame frame = new JFrame("Drawing Demo"); // Construct a new window frame.setSize(640, 480); // Dimensions of the window in pixels. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Quit Java when window closed. DrawingDemo dd=new DrawingDemo(); // Construct the panel frame.add(dd); // and add it to the window. frame.setVisible(true); // Make the window visible to the user. } }
There is more drawing in the original file DrawingDemo.java. A screenshot of the DrawingDemo is shown to the right.
The most useful resource for learning to draw things is Oracle's Introduction to Graphics2D.
In the paintComponent method we construct a Graphics2D object. The Graphics2D has draw and fill methods for drawing Shapes. The things that can be drawn with a Graphics2D object must implement the the Shape interface. (See java.awt.Shape.)
Many shapes are built into Java including line segments, rectangles, ellipses, …. To build polygons use GeneralPath. The GeneralPath class also allows you to use Bézier curves to build shapes. See Oracle's tutorial.
One important thing to know about Shapes is that they can be transformed with an affine transformation. See the AffineTransform class, and in particular the method createTransformedShape(). This is very useful for drawing mathematical objects, as we will see.
public class PolygonalPathPanel extends JPanel { private PolygonalPath p; private Rectangle2D display_box; private AffineTransform current_transform; public PolygonalPathPanel(PolygonalPath path) { p = path; display_box=PathUtil.boundingBox(p); this.setBackground(Color.WHITE); } ... }
In the above code, display_box will store a rectangle we want to guarantee we display, and current_transform will be an affine transformation which moves the display_box into the rectangle representing the screen.
Our PolygonalPathPanel will contain a method which returns an affine transformation which sends display_box into the screen coordinates. This will be called whenever we draw, because the window can change sizes.
public class PolygonalPathPanel extends JPanel { private PolygonalPath p; private Rectangle2D display_box; private AffineTransform current_transform; public PolygonalPathPanel(PolygonalPath path) {...} /** This function returns an affine transform which sends display_box * into the rectangle representing screen coordinates for this panel. */ private AffineTransform getTransform() {...} public void paintComponent(Graphics gfx) { super.paintComponent(gfx); Graphics2D g = (Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); current_transform = getTransform(); // ... Do some drawing... } }
The contents of getTransform() can be seen in PolygonalPathPanel.java.
When we draw our polygonal curve we use the current_transform to change the coordinates of line segments making up our path from "math coordinates" to screen coordinates.
public void paintComponent(Graphics gfx) { super.paintComponent(gfx); Graphics2D g = (Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); current_transform = getTransform(); // Draw in black, with lines of width equal to one pixel. g.setColor(Color.BLACK); g.setStroke(new BasicStroke(1)); EdgeIterator it = p.iterator(); while (it.hasNext()) { // iterate over the edges of p. Segment s = it.next(); Line2D line_segment = new Line2D.Double(s.startingPoint().re(), s.startingPoint().im(), s.endingPoint().re(), s.endingPoint().im()); // Convert the line segment into screen coordinates, then draw it. g.draw(current_transform.createTransformedShape(line_segment)); } }
The full source can be seen in PolygonalPathPanel.java.
The KochSnowflakeDisplay class demonstrates the use of PolygonalPathPanel to display an approximation to the KochSnowflake. You can view the code in KochSnowflakeDisplay.java.
A screenshot of this program is shown below.
One of the great things about creating graphics in Java is that they can be easily converted to publication quality graphics.
The VectorGraphics package created by FreeHEP can be used to produce graphics in a variety of formats. A great thing about this is that the same code that is used to draw the graphics on the screen can be used to produce the images. You can learn more about this package on the VectorGraphics website.
The package has a built in ExportDialog which can be used to output images in many formats. See the VectorGraphics Manual for details.
In order to make use of their package, you need to download it. Visit the VectorGraphics download site, and download vectorgraphics-2.1.1-bin.zip or vectorgraphics-2.1.1-bin.tar.gz (or a newer version if it exists). Unpack the files and store them. (You might store the unpacked files in a "java library" directory.)
The most important files are the .jar files located in the lib folder you unpacked.
To use the VectorGraphics package in a NetBeans project, you click the "File" menu and select "Project Properties". A new window will pop up. Select "Libraries" at the left. Then click the button "Add JAR/Folder". Select all the contents of the lib folder in your VectorGraphics download and click "ok." The window should look as below. Click "ok" to close it.
The PolygonalPathDisplay class demonstrates a window with a menu bar. There is only a "File" menu on the bar. The menu has two entries, "Export" and "Close". Clicking "Close" will close the window, and clicking "Export" will launch a dialog allowing you to export the image using the VectorGraphics package.
The source code for the PolygonalPathDisplay class is available in PolygonalPathDisplay.java.
You should be able to see how you would be able to add more menu items.