6.08 - Components and Graphics



The Canvas class

As you have previously, there are many components that we can use. 

Graphical components have a set of methods that we can override and replace, in order to build components with custom behaviour. Java provides us with the Canvas class that acts like any other component, but also allows you to draw graphics directly to it - just like an artist's canvas. The other advantage of using a component is that you can take advantage of the layout managers to control how the application will place the component as it is moved or resized. The Canvas component specifies its co-ordinate system at (0,0) for the top left-hand corner.

Canvas components can handle mouse events. You must subclass Canvas to add the behaviour you require, modifying the paint() method. So, for example:

Write a custom Canvas:

public class CustomCanvas extends Canvas {

    public void paint(Graphics g){
            g.drawString("Test", 10, 10);
    }
}

Then add it to the Application:
public class CanvasApplication extends Frame {

    private CustomCanvas canvas;

    public CanvasApplication(){
...
            this.canvas = new CustomCanvas();
            this.add(canvas, BorderLayout.CENTER);
         ...
    }

    public static void main(String[] args) {
            new CanvasApplication();
    }
}

This provides your own Canvas class and you can create as many objects of this as you require - each one only displaying "Test" at the (x,y) location (10,10). 

A Functional Canvas Example

Here is an example of an application that uses the Canvas class. It combines a BorderLayout with a Button component and a modified Canvas component. The application generates 200 random circles with different colours every time the "Refresh" button is pressed. Figure 6.X, “The Canvas Application” displays the application running, and you can also run it yourself using the source code below.


Figure 6.X The Canvas Application with two different random sets of circles


1234567891011121314151617181920212223242526272829
package ee402;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;

@SuppressWarnings("serial")
public class CustomCanvas extends Canvas {

        int width, height;
        
        public CustomCanvas(int width, int height){
                this.setSize(width,height);
                this.width = width;
                this.height = height;
                this.update();
        }
        
        public void update() { this.repaint(); }
        
        public void paint(Graphics g){
                for(int i=0; i<200; i++){
                        Color tempColor = new Color((float)Math.random(),
                                        (float)Math.random(), (float)Math.random());
                        g.setColor(tempColor);
                        g.drawOval((int)(Math.random()*width),(int)(Math.random()*height), 20, 20);
                }
        }
}


1234567891011121314151617181920212223242526272829303132333435363738394041424344
package ee402;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

@SuppressWarnings("serial")
public class CanvasApplication extends Frame implements ActionListener, WindowListener{
        
        private CustomCanvas canvas;
        private Button refresh;
        
        public CanvasApplication(){
                super("Canvas Application");
                this.refresh = new Button("Refresh");
                this.add(refresh, BorderLayout.NORTH);
                this.refresh.addActionListener(this);
                this.canvas = new CustomCanvas(250,250);
                this.add(canvas, BorderLayout.CENTER);
                this.addWindowListener(this);
                this.pack();
                this.setVisible(true);
        }

        public void windowActivated(WindowEvent arg0) {}
        public void windowClosed(WindowEvent arg0) {}
        public void windowClosing(WindowEvent arg0) { System.exit(0); }
        public void windowDeactivated(WindowEvent arg0) {}
        public void windowDeiconified(WindowEvent arg0) {}
        public void windowIconified(WindowEvent arg0) {}
        public void windowOpened(WindowEvent arg0) {}
        
        public void actionPerformed(ActionEvent e) {
                if(e.getSource().equals(refresh)){
                        this.canvas.update();
                }
        }

        public static void main(String[] args) {
                new CanvasApplication();
        }
}

In this piece of code I have written two classes CanvasApplication and CustomCanvas. In the CanvasApplication class an object is created of the CustomCanvas class and this is added to the "Center" of the BorderLayout and added the Button object to the "North". When the button "Refresh" is pressed the update() method of our CustomCanvas is called.

The CustomCanvas class extends Canvas and overwrites the paint() method. The update() just calls this.repaint() which calls the paint() method indirectly, without requiring a Graphics object. To create the Color object we used the constructor:

    Color(float red, float green, float blue);

Where each float has the value 0.0 to 1.0 representing the red, green and blue level. In this case we used Math.random() which generates a double with a value between 0.0 and 1.0. Since it is a double it needs to be converted to a float using the cast conversion. In the drawOval() method the (x,y) position is given by a random number between 0 and 200, by using the Math.random() method and multiplying the value by 200 and then cast converting the double value to an int.


These notes are copyright Dr. Derek Molloy, School of Electronic Engineering, Dublin City University, Ireland 2013-present. Please contact him directly before reproducing any of the content in any way.
ċ
CanvasApplication.java
(1k)
Derek Molloy,
17 Nov 2013, 12:00
ċ
CustomCanvas.java
(1k)
Derek Molloy,
17 Nov 2013, 12:00
Comments