Search code examples
javaswingjframejcomponent

Draw on Jframe image


I want to read a file to get some points and then draw these points on an image. Currently, I am able to draw values on the image, but the file is read three times and the rectangles are drawn three times. I don't know where is the problem. Below is the code. The Read() function works fine seperately so I didn't include it in the code.

P.S: I am beginner in JAVA and don't know much about JFrame and Jcomponent.

       public class LoadImageApp extends JComponent {   

    BufferedImage img;

    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        g.drawImage(img, 0, 0, null);

        Read(g);// This is the function in which I read a file. 
    }

 public LoadImageApp() {
       try {
           img = ImageIO.read(this.getClass().getResource("/New York.jpg"));
       } catch (IOException e) {
       }

    }

    public Dimension getPreferredSize() {
        if (img == null) {
             return new Dimension(100,100);
        } else {
           return new Dimension(img.getWidth(null), img.getHeight(null));
       }
    }



 public static void main(String[] args) {


        JFrame f = new JFrame("Load Image Sample");

        f.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
        LoadImageApp img = new LoadImageApp();
        f.add(img);
        f.pack();
        f.setVisible(true);


    }
}

Solution

  • Do not, do not, DO NOT read from a file from within any painting method such as paintComponent(...). :)

    1. That method should be for painting only. The more you slow it down, the less responsive your GUI will seem.
    2. You cannot control how many times the method gets called, since it is not under direct control by you, the programmer.
    3. You can't even control fully if the paintComponent method gets called, since the JVM might decide that too many requests for redraw are being stacked up, and it may not honor all of them.

    Instead

    • read in the data once in a constructor or something similar.
    • I would create a read method that stores my points in an ArrayList<Point>, and then inside of the paintComponent method, iterate through that ArrayList using a for loop and draw them.
    • If the points don't change during your program's run, you could even draw them directly on to the BufferedImage by getting its Graphics context and using that to paint the points on to the image, and then show the new BufferedImage in your paintComponent method.

    Other suggestions:

    • That empty catch block where you read your image is a dangerous thing to do. It's the coding equivalent of driving a motorcycle with your eyes closed. At least print out a stacktrace.
    • The WindowListener is not needed. Instead simply set your JFrame's defaultCloseOperation to JFrame.EXIT_ON_CLOSE: f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);