Home  Contents

Basic drawing

In this part of the Java 2D tutorial, we will do some basic drawing.

Points

The most simple graphics primitive is point. It is a single dot on the window. Interesingly, there is no method to draw a point in Java 2D. (Or I could not find it.) To draw a point, I used a drawLine() method. I used one point twice.

Points.java
package points; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import javax.swing.JPanel; import javax.swing.JFrame; import java.util.Random; public class Points extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setColor(Color.blue); Dimension size = getSize(); Insets insets = getInsets(); int w = size.width - insets.left - insets.right; int h = size.height - insets.top - insets.bottom; Random r = new Random(); for (int i=0; i<1000; i++) { int x = Math.abs(r.nextInt()) % w; int y = Math.abs(r.nextInt()) % h; g2d.drawLine(x, y, x, y); } } public static void main(String[] args) { JFrame frame = new JFrame("Points"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new Points()); frame.setSize(250, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }

One point is difficult to observe. Why not paint 1000 of them? In our example, we do so. We draw 1000 blue points on the panel.

  g2d.setColor(Color.blue);

We will paint our points in blue color.

 Dimension size = getSize();
 Insets insets = getInsets();

The size of the window includes borders and titlebar. We don't paint there.

 int w =  size.width - insets.left - insets.right;
 int h =  size.height - insets.top - insets.bottom;

Here we calculate the area, where we will effectively paint our points.

 Random r = new Random();
 int x = Math.abs(r.nextInt()) % w;
 int y = Math.abs(r.nextInt()) % h;

We get a random number in range of the size of area, that we computed above.

 g2d.drawLine(x, y, x, y);

Here we draw the point. As I already said, we use a drawLine() method. We specify the same point twice.


Points
Figure: Points

Lines

A line is a simple graphics primitive. To draw a line, we use the drawLine() method.

Lines.java
package com.zetcode; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JPanel; public class Lines extends JPanel { int coords[][]; int count; public Lines() { coords = new int [100][2]; count = 0; addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent event) { if (event.getButton() == event.BUTTON1) { int x = event.getX(); int y = event.getY(); coords[count][0] = x; coords[count][1] = y; count++; } if (event.getButton() == event.BUTTON3) { drawLines(); count = 0; } } }); } public void drawLines() { Graphics g = this.getGraphics(); Graphics2D g2d = (Graphics2D) g; int w = getWidth(); int h = getHeight(); RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHints(rh); g2d.clearRect(0, 0, w, h); for ( int i = 0; i < count-1; i++ ) { for (int j = 0; j < count-1; j++) g2d.drawLine(coords[i][0], coords[i][1], coords[j][0], coords[j][1]); } } public static void main(String[] args) { Lines lines = new Lines(); JFrame frame = new JFrame("Lines"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(lines); frame.setSize(300, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }

In our example, we will draw a lot of lines. Click a lot on the panel with the left mouse button. After that, click with a right button. Each of the dots where you clicked will be connected with other dots. This way we create a complex structure.


Lines
Figure: Lines

BasicStroke

The BasicStroke class defines a basic set of rendering attributes for the outlines of graphics primitives. These rendering attributes include width, end caps, line joins, miter limit and dash attributes.

BasicStrokes.java
import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; public class BasicStrokes extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; float[] dash1 = { 2f, 0f, 2f }; float[] dash2 = { 1f, 1f, 1f }; float[] dash3 = { 4f, 0f, 2f }; float[] dash4 = { 4f, 4f, 1f }; g2d.drawLine(20, 40, 250, 40); BasicStroke bs1 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash1, 2f ); BasicStroke bs2 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash2, 2f ); BasicStroke bs3 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash3, 2f ); BasicStroke bs4 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash4, 2f ); g2d.setStroke(bs1); g2d.drawLine(20, 80, 250, 80); g2d.setStroke(bs2); g2d.drawLine(20, 120, 250, 120); g2d.setStroke(bs3); g2d.drawLine(20, 160, 250, 160); g2d.setStroke(bs4); g2d.drawLine(20, 200, 250, 200); } public static void main(String[] args) { JFrame frame = new JFrame("BasicStroke"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new BasicStroke()); frame.setSize(280, 270); frame.setLocationRelativeTo(null); frame.setVisible(true); } }

In this example, we show various types of dashes. A dash attribute is a pattern, which is created by mixing opaque and transparent sections.

 float[] dash1 = { 2f, 0f, 2f };
 float[] dash2 = { 1f, 1f, 1f };
 float[] dash3 = { 4f, 0f, 2f };
 float[] dash4 = { 4f, 4f, 1f };

Here we define four different dash patterns.

 BasicStroke bs1 = new BasicStroke(1, BasicStroke.CAP_BUTT, 
     BasicStroke.JOIN_ROUND, 1.0f, dash1, 2f );

Construction of a typical BasicStroke object.

 g2d.setStroke(bs1);

We use the setStroke() method to apply the BasicStroke to the current graphics context.

 g2d.drawLine(20, 80, 250, 80);

Finally, we draw the line.


BasicStroke
Figure: BasicStroke

Caps

Caps are decorations applied to the ends of unclosed subpaths and dash segments. There are three different end caps in Java 2D. CAP_BUTT, CAP_ROUND, and CAP_SQUARE.

Caps.java
package com.zetcode.caps; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JFrame; import javax.swing.JPanel; public class Caps extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; RenderingHints rh = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHints(rh); BasicStroke bs1 = new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL); g2d.setStroke(bs1); g2d.drawLine(20, 30, 250, 30); BasicStroke bs2 = new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL); g2d.setStroke(bs2); g2d.drawLine(20, 80, 250, 80); BasicStroke bs3 = new BasicStroke(8, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL); g2d.setStroke(bs3); g2d.drawLine(20, 130, 250, 130); BasicStroke bs4 = new BasicStroke(); g2d.setStroke(bs4); g2d.drawLine(20, 20, 20, 140); g2d.drawLine(250, 20, 250, 140); g2d.drawLine(254, 20, 254, 140); } public static void main(String[] args) { JFrame frame = new JFrame("Caps"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new Caps()); frame.setSize(300, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }

In our example, we show all three types of end caps.

 g2d.drawLine(20, 20, 20, 140);
 g2d.drawLine(250, 20, 250, 140);
 g2d.drawLine(254, 20, 254, 140);

We draw three vertical lines to explain the differences among the end caps. Lines with CAP_ROUND and CAP_SQUARE are bigger than the line with CAP_BUT. Exactly how much bigger depends on the line size. In our case a line is 8px thick. Lines are bigger by 8px, 4px on the left and 4px on the right. It is clear from the picture.


Caps
Figure: Caps

Joins

Line joins are decorations applied at the intersection of two path segments and at the intersection of the endpoints of a subpath. There are three decorations are. JOIN_BEVEL, JOIN_MITER, and JOIN_ROUND.

Caps.java
package com.zetcode.joins; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; public class Joins extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; BasicStroke bs1 = new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL); g2d.setStroke(bs1); g2d.drawRect(15, 15, 80, 50); BasicStroke bs2 = new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); g2d.setStroke(bs2); g2d.drawRect(125, 15, 80, 50); BasicStroke bs3 = new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); g2d.setStroke(bs3); g2d.drawRect(235, 15, 80, 50); } public static void main(String[] args) { JFrame frame = new JFrame("Joins"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new Joins()); frame.setSize(340, 110); frame.setLocationRelativeTo(null); frame.setVisible(true); } }

This code example show three different line joins in action.

 BasicStroke bs1 = new BasicStroke(8, BasicStroke.CAP_ROUND, 
     BasicStroke.JOIN_BEVEL);
 g2d.setStroke(bs1);
 g2d.drawRect(15, 15, 80, 50);

Here we create a rectangle with a JOIN_BEVEL join.


Joins
Figure: Joins