Home > Software design >  How can a JPanel be changed after added to JFrame?
How can a JPanel be changed after added to JFrame?

Time:11-01

I have created a subclass of JPanel to display images. I instantiate this in the constructor of a JFrame and add it to that JFrame. This works perfectly. Then I have added a button with an ActionListener to change that Image. My problem is that the JFrame won´t update although I have tried repainting etc.

The subclass of JPanel:

public class ImagePanel extends JPanel {

    BufferedImage bf;
    public ImagePanel(String dateiname)
    {
        try {
            bf = ImageIO.read(new File(dateiname));


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void paint(Graphics g)
    {
        g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
    }
}

The JFrame is basically this

public class Hauptfenster extends JFrame {

private JButton changeImage;
private JPanel buttonPanel;
private ImagePanel ip;


public Hauptfenster {

ip = new ImagePanel("first_image.jpg");

buttonPanel = new JPanel();
buttonPanel.add(changeImage);

changeImage.addActionListener((e) -> {

ip = new ImagePanel("new_image.jpg");
ip.setVisible(true);


});


this.add(buttonPanel);
this.add(ip);
this.setVisible(true);

}

}

Why doesn´t the method in the ActionListener update the ip component in the JFrame Hauptfenster?

CodePudding user response:

When you do ip = new ImagePanel("new_image.jpg"); you're creating a whole new ImagePanel that has nothing to do with your current layout. You could.

remove(ip);
ip = new ImagePanel("new_image.jpg");
add(ip);
repaint();

Another way you could do it is to just change the buffered image.

Add the following method to your image panel.

public void loadImage(String dateiname) {
    try {
        bf = ImageIO.read(new File(dateiname));


    } catch (IOException e) {
        e.printStackTrace();
    }
}

Then in your action listener.

ip.loadNewImage("new_image.jpg");
ip.repaint();

You have a bunch of bad habits going on in your code though.

Such as, override paintComponent instead of paint and it should look like.

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
}

That way transparency will be handled correctly.

You shouldn't extend JFrame, you should just create a JFrame.

When you add components, you there is a layout manager involved. It's good to be aware of that and handle things accordingly. I would change your constructor to.

public Hauptfenster() {

    JFrame frame = new JFrame();
    ip = new ImagePanel("first_image.jpg");
    buttonPanel = new JPanel();
    changeImage = new JButton("change image");
    buttonPanel.add(changeImage);

    changeImage.addActionListener((e) -> {
        frame.remove(ip);
        ip = new ImagePanel("new_image.jpg");
        frame.add(ip, BorderLayout.CENTER);
        frame.repaint();
    });
    frame.add(buttonPanel, BorderLayout.SOUTH);
    frame.add(ip, BorderLayout.CENTER);
    frame.setVisible(true);
}

If you need more help, you'll need to actually make your example compilable. There are too many errors right now.

  • Related