Search code examples
javaimageswingjlabel

Image drawing on a Java component


I'm trying to create a simple application that draws graphics...

package Tests.Drawing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.border.EtchedBorder;

public class DrawingTest extends JFrame
{
    private Canvas drwArea;
    private JButton btnClear;

    public static void main(String[] args)
    {
        DrawingTest StartForm = new DrawingTest();
        StartForm.setVisible(true);
    }


    public DrawingTest()
    {
        //Window...
        this.setTitle("Drawing objects test00");
        this.setBounds(0,0,510,500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        //Drawing area...
        drwArea = new Canvas();
        drwArea.setBounds(0, 0, 400, 450);      
        drwArea.setBackground(Color.WHITE);
        drwArea.setOpaque(true);
        drwArea.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
        drwArea.addMouseMotionListener(new MouseMotionAdapter()
        {
            @Override
            public void mouseDragged(MouseEvent e)
            {
                //Write code to paint on the image...
            }
        });

        this.getContentPane().add(drwArea);
        //Clear button...
        btnClear = new JButton("Clear");
        btnClear.setBounds(410,50,70,30);
        btnClear.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                //Write code to clear the image...
            }
        });

        this.getContentPane().add(btnClear);

    }

    private class Canvas extends JLabel
    {
        @Override
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            //The idea of overriding this method is
            //achieving persistence...
        }
    }

}

I have seen that the typical component to draw on is a Jlabel (Is there anyone better by the way?). Using the method “getGraphics” I can use an object that has several methods to paint on the component. My problem is that instead of painting directly on the JLabel, I would like to paint on an image (in memory) and once the painting has finished, send the result to the JLabel. How can I do this? I'm a bit lost...

Thanks in advance.


Solution

  • I would like to paint on an image (in memory)

    I suggest that you then create a BufferedImage object of the desired size, get its Graphics2D object by calling createGraphics() on it, and draw on it using this Graphics2D object.

    and once the painting has finished, send the result to the JLabel

    Then create an ImageIcon out of the BufferedImage above by simply calling

    Icon myIcon = new ImageIcon(myBufferedImage);
    

    and then setting the JLabel's icon via myLabel.setIcon(myIcon);

    Also you could draw to a BufferedImage that is being displayed within a JPanel's paintComponent method, and this may be an even better way to go if you want to update the image while the program is running. For more on this, please have a look at some of these examples.

    Other comments:

    • Don't draw with a Graphics object obtained by calling getGraphics() on a component. This will return a Graphics object that is short lived, risking disappearing graphics or worse, a NullPointerException. Instead, draw in the JPanel's paintComponent(...) method either directly, or indirectly by drawing on a BufferedImage (yes, you can get its Graphics object via getGraphics()) and then drawing the BufferedImage to the GUI within the paintComponent method.
    • While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.