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. Interestingly, 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;
import javax.swing.SwingUtilities;

public class Lines extends JFrame {

    int coords[][];
    int count;

    public Lines() {
        initUI();
    }

    public final void initUI() {

        coords = new int[100][2];
        count = 0;

        JPanel panel = new JPanel();
        panel.setLayout(null);

        setTitle("Lines");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300, 200);
        setLocationRelativeTo(null);
        
        addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent event) {
                if (event.getButton() == MouseEvent.BUTTON1) {

                    int x = event.getX();
                    int y = event.getY();

                    coords[count][0] = x;
                    coords[count][1] = y;
                    count++;
                }

                if (event.getButton() == MouseEvent.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) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Lines lns = new Lines();
                lns.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

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