James MV
James MV

Reputation: 8727

Change Image in JFrame?

I've been working through the Oracle tutorial for images this one here:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;

public class LoadImageApp extends Component {

    BufferedImage img;

    public void paint(Graphics g) {
        g.drawImage(img, 0, 0, null);
    }

    public LoadImageApp() {
       try {
           img = ImageIO.read(new File("strawberry.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);
                }
            });

        f.add(new LoadImageApp());
        f.pack();
        f.setVisible(true);
    }
}

I want to change the image that appears in the JFrame. If I say:

f.add(new LoadImageApp());      
f.revalidate();
f.repaint();

The new image will appear, behind the current one. What I'd like to do is remove the previous image and replace, but I can't work out how I'd go about doing this with this snippet of code?

Upvotes: 2

Views: 12489

Answers (3)

londox
londox

Reputation: 343

Here my contribution, with a main for testing. The idea is changing the base JPanel where the image is changed. This class could be added in another JPanel or JFrame and still you will have the access to change the image.

public class ImageButton extends JPanel {
    
    public  JLabel imageLabel;
    
    public ImageButton() {
        super();
        iniGUI();
    }

    private void iniGUI() {
        
        JPanel panel = new JPanel();
        imageLabel = new JLabel(" ");
        panel.setLayout(new BorderLayout());
        panel.add(imageLabel, BorderLayout.NORTH);
        
        JButton clickButton = new JButton("Select...");
        panel.add(clickButton, BorderLayout.SOUTH);
        
        clickButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                JFileChooser fc = new JFileChooser();
                int result = fc.showOpenDialog(null);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File file = fc.getSelectedFile();
                    try {
                        imageLabel.setIcon(new ImageIcon(ImageIO.read(file)));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        panel.setPreferredSize(new Dimension(200, 200));
        panel.setBorder(BorderFactory.createLineBorder(Color.black));
        
        this.add(panel, BorderLayout.CENTER);
    }
    
    public static void main(String...arg){
        
        JFrame cadre = new javax.swing.JFrame(" ");
    
        cadre.setContentPane(new  ImageButton());
        cadre.setPreferredSize(new Dimension(600, 600));
        cadre.setLocation(300, 300);
        cadre.pack();
        cadre.setVisible(true);
        cadre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Upvotes: 0

camickr
camickr

Reputation: 324207

Why don't you just use a JLabel to display the image? Then to change the image you just invoke the setIcon(...) method.

If you do need to do custom painting then:

  1. For a Swing application you should extend JComponent, not Component

  2. You should be overriding paintComponent(), not paint()

  3. If you want to change the image then create a method like setImage() to change the image. Then in that method you invoke repaint() to force the component to repaint itself. There is no need to create a new component and replace the component on the GUI.

Upvotes: 5

GETah
GETah

Reputation: 21459

The issue you have is that you are stacking up images without removing the old ones. Do the following instead: In the original code:

BufferedImage img = new LoadImageApp();
f.add(img);
f.pack();
f.setVisible(true);

When you want to load another image:

img = new LoadImageApp();
// No need to add the image to the frame again, just refresh
f.repaint();

Upvotes: 0

Related Questions