Robin Schneider
Robin Schneider

Reputation: 38

JLayeredPane image not showing up

I have an Image and all I want is to pack this Image into a JLabel and add it to my JLayeredPane to layer multiple images later. It worked with one Image without a JLayeredPane, but when using the JLayeredPane I only see my border. I have to layer multiple Images so ypu can configurate a Pizza and see your customised Pizza.

package view;

import javax.swing.*;
import java.awt.*;

/**
 * ImagePanel used to scale and display an image
 */

public class ImagePanel extends JPanel {
private JLayeredPane layeredPane;

/**
 * Setup an ImagePanel, get the image, scale it and set it as a label to display it
 */
public ImagePanel(){

    layeredPane = new JLayeredPane();
    layeredPane.setPreferredSize(new Dimension(300, 300));
    layeredPane.setBorder(BorderFactory.createTitledBorder("Your Pizza"));
    ImageIcon icon = new ImageIcon(getClass().getResource("/images/pizzaboden.png"));
    JLabel imgLabel = new JLabel(icon);
    layeredPane.add(imgLabel);
    add(layeredPane);

}
}

Reading the image works, this is the way I read it earlier and it worked fine:

My datafield

private ImageIcon imageIcon;
private ImageIcon scaledImageIcon;
private JLabel imageLabel;
private Image image;
private Image scaledImage;

My Constructor

imageIcon = new ImageIcon(getClass().getResource("/images/pizzaboden.png"));
    image = imageIcon.getImage();
    scaledImage = image.getScaledInstance(280, 280, Image.SCALE_SMOOTH);
    scaledImageIcon = new ImageIcon(scaledImage);
    imageLabel = new JLabel(scaledImageIcon);
    add(imageLabel);

What I get

Upvotes: 1

Views: 695

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

When you add something to a JLayeredPane, you need to specify where the component is being added in the X/Y dimension as well as where in the layered dimension, as per the JLayeredPane tutorial, and you don't do this. You also need to give the JLabel a size since it's preferred size is not respected by the JLayeredPane. Something like

imgLabel.setSize(imgLabel.getPreferredSize());
imgLabel.setPosition(0, 0);
layeredPane.add(imgLabel, JLayeredPane.DEFAULT_LAYER);

may be adequate.

Also, have you tested independent of this current program to make sure that the image is being read in appropriately? Also, you're adding to a FlowLayout using JPanel -- are you sure that you want to do this? Perhaps better would be to give your ImagePanel a BorderLayout.


Note that if I were doing something like this, show multiple overlapping images in a Swing GUI, I wouldn't use a JLayeredPane but instead would draw images (BufferedImages) in the paintComponent(Graphics g) method of a single drawing JPanel, and I'd add and remove images from the GUI when desired, then call repaint() on the drawing JPanel.

For instance, if you give the drawing JPanel an ArrayList of images like so:

private List<Image> images = new ArrayList<>();

You can draw any images held by this list by iterating through the list in the paintComponent method:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    for (Image image : images) {
        g.drawImage(image, 0, 0, this);
    }
}

And you can add and remove images easily:

public void clearImages() {
    images.clear();
    repaint();
}

public void removeImage(Image image) {
    images.remove(image);
    repaint();
}

public void addImage(Image image) {
    images.add(image);
    repaint();
}

For example, here is test-of-concept code that you can run that demonstrates what I mean:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;

public class MultipleImages extends JPanel {
    private static final String BULLS_EYE_PATH = "https://upload.wikimedia.org/wikipedia/"
            + "commons/thumb/3/36/Roundel_of_the_Serbian_Air_Force_1915.svg/"
            + "300px-Roundel_of_the_Serbian_Air_Force_1915.svg.png";
    private static final String CHINESE_CHAR_PATH = "https://upload.wikimedia.org/"
            + "wikipedia/commons/1/1a/%E9%9D%91-red.png";
    private static final String HOCKY_PATH = "https://upload.wikimedia.org/wikipedia/"
            + "commons/thumb/e/eb/Ice_hockey_pictogram.svg/"
            + "300px-Ice_hockey_pictogram.svg.png";
    private static final String[] LABELS = {"Bulls Eye", "Chinese Character", "Hockey"};
    private static final String[] IMAGE_PATHS = {BULLS_EYE_PATH, CHINESE_CHAR_PATH, HOCKY_PATH};
    private Map<String, Image> imageMap = new HashMap<>();
    private List<JCheckBox> checkBoxes = new ArrayList<>();
    private ImagePanel imagePanel = new ImagePanel();

    public MultipleImages() throws IOException {
        for (int i = 0; i < IMAGE_PATHS.length; i++) {
            URL imgUrl = new URL(IMAGE_PATHS[i]);
            BufferedImage img = ImageIO.read(imgUrl);
            imageMap.put(LABELS[i], img);
        }

        ActionListener checkBoxListener = e -> {
            imagePanel.clearImages();
            for (JCheckBox checkBox : checkBoxes) {
                if (checkBox.isSelected()) {
                    String label = checkBox.getActionCommand();
                    imagePanel.addImage(imageMap.get(label));
                }
            }
            imagePanel.repaint();
        };
        JPanel checkBoxPanel = new JPanel(new GridLayout(0, 1));
        for (String label : LABELS) {
            JCheckBox checkBox = new JCheckBox(label);
            checkBox.setActionCommand(label);
            checkBoxes.add(checkBox);
            checkBoxPanel.add(checkBox);
            checkBox.addActionListener(checkBoxListener);
        }
        JPanel rightPanel = new JPanel(new BorderLayout());
        rightPanel.add(checkBoxPanel, BorderLayout.PAGE_START);

        setLayout(new BorderLayout());
        add(rightPanel, BorderLayout.LINE_START);
        add(imagePanel);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Multiple Images");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try {
            frame.getContentPane().add(new MultipleImages());
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

public class ImagePanel extends JPanel {
    private static final int PREF_W = 300;
    private static final int PREF_H = PREF_W;
    private static final Color BACKGROUND = Color.WHITE;
    private List<Image> images = new ArrayList<>();

    public ImagePanel() {
        setBackground(BACKGROUND);
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Image image : images) {
            g.drawImage(image, 0, 0, this);
        }
    }

    public void clearImages() {
        images.clear();
        repaint();
    }

    public void removeImage(Image image) {
        images.remove(image);
        repaint();
    }

    public void addImage(Image image) {
        images.add(image);
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }
}

Upvotes: 1

Related Questions