Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make canvas with Swing?

People also ask

What is canvas in Java Swing?

A Canvas component represents a blank rectangular area of the screen onto which the application can draw or from which the application can trap input events from the user. An application must subclass the Canvas class in order to get useful functionality such as creating a custom component.

Is canvas in Swing?

Canvas is a heavyweight component. That is to say that it is controlled by the underlying windowing system. The result is that it will typically be drawn over the top of Swing components, without respect to z-order or clipping (putting it in a scroll pane will give odd behaviour).

What are frames in Java?

A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and supports button components that close or iconify the window. Applications with a GUI usually include at least one frame. Applets sometimes use frames, as well.


In order to make a custom 'Canvas' in swing you usually write a subclass of a JPanel. Then, you must overwrite the protected paintComponent(Graphics g) method of JPanel.

In the paint method, you can call methods on the Graphics object to actually draw on the JPanel.

As always, the Java Tutorials have a great reference on this to get you started.


You'll probably want to make a subclass of JPanel and implement your own way of painting components you want to draw onto the panel.

The basic approach will probably be along the line of assigning a MouseListener to the subclass of JPanel, then implement painting functionality.

The basic idea may be something along the line of:

class MyCanvas extends JPanel implements MouseListener
{
    Image img;      // Contains the image to draw on MyCanvas

    public MyCanvas()
    {
        // Initialize img here.
        this.addMouseListener(this);
    }

    public void paintComponent(Graphics g)
    {
        // Draws the image to the canvas
        g.drawImage(img, 0, 0, null);
    }

    public void mouseClicked(MouseEvent e)
    {
        int x = e.getX();
        int y = e.getY();

        Graphics g = img.getGraphics();
        g.fillOval(x, y, 3, 3);
        g.dispose();
    }

    // ... other MouseListener methods ... //
}

The above example is incomplete (and not tested -- it definitely won't compile), but it gives an idea about how to implement a MyCanvas class in which a user can click on and draw circles.

The img object is used to hold the image of the canvas. The paintComponent method is used to paint the img object to the canvas. In the mouseClicked method, the Graphics object associated with img is retrieved in order to fillOval onto the image.

Since one the requirements is to paste images onto the canvas, it may be a good idea to hold some Images that you want to paste into the canvas. Perhaps something along the line of:

Image[] myImages;    // Used to store images to paint to screen.

Then, in the routine to paint the image onto img stored in MyCanvas:

g.drawImage(myImage[INDEX_OF_DESIRED_IMAGE], 0, 0, null);

By using the drawImage method of the Graphics object, other Images can be drawn onto Images.


As for the question on AWT and Swing, yes, it is true that you do not want to mix components from the AWT and Swing, as they differ in the way they render GUI components. AWT is based on heavyweight components, meaning they native windowing for painting the GUI, while Swing is based on lightweight components, meaning the GUI is drawn by Java itself without using native components.

A good guide on the difference of AWT and Swing is provided in Painting in AWT and Swing article from Sun.


Simply subclass JComponent.

JPanel is an inappropriate class. It is often suggested as it appears to have setOpaque(true) invoked on it automatically. It's actually the PL&F which does that, and whether or not it actually happens is implementation and vendor dependent.

Canvas is a heavyweight component. That is to say that it is controlled by the underlying windowing system. The result is that it will typically be drawn over the top of Swing components, without respect to z-order or clipping (putting it in a scroll pane will give odd behaviour).


You might want to look at the Minueto API. It is a very simple to use graphics api, and you can combine the Java event listening with it to provide your drawing capability.

http://minueto.cs.mcgill.ca/