Question

I'm creating a program that features a grid of 12 JPanels. When the "add image" button is pressed, an image appears in the first JPanel in the grid and a counter is incremented by one. From then onwards, every time the "add image" is clicked again, an image would be added to the next JPanel. For some reason, the button only adds an image to the first JPanel and then stops working. Here's the code I've got so far.

public class ImageGrid extends JFrame {

static JPanel[] imageSpaces = new JPanel[12];
int imageCounter = 0;

ImageGrid() {
    this.setTitle("Image Grid");
    setSize(750, 750);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    JPanel p3 = new JPanel();
    p3.setLayout(new GridLayout(3, 4, 10, 5));
    p3.setBackground(Color.WHITE);
    p3.setOpaque(true);
    p3.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

    for (int j = 0; j < imageSpaces.length; j++) {
        imageSpaces[j] = setImageSpace();

        p3.add(imageSpaces[j]);
    }

    MyButtonPanel p1 = new MyButtonPanel();

    add(p1, BorderLayout.SOUTH);
    add(p3, BorderLayout.CENTER);

}

public JPanel setImageSpace() {

    JPanel test;
    test = new JPanel();
    test.setOpaque(true);
    test.setPreferredSize(new Dimension(100, 100));
    return test;
}

class MyButtonPanel extends JPanel implements ActionListener {

    final JButton addImage = new JButton("Add Image");

    ImageIcon lorryPicture = new ImageIcon(ImageGrid.class.getResource("/resources/lorry.png"));
    JLabel lorryImage = new JLabel(lorryPicture);

    MyButtonPanel() {
        add(addImage);
        addImage.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == addImage) {
            imageSpaces[imageCounter].add(lorryImage);
            revalidate();
            repaint();
            imageCounter++;
        }
    }
}
public static void main(String[] args) {

    ImageGrid test = new ImageGrid();
    test.setVisible(true);
}
}
Was it helpful?

Solution

You should be revalidating and repainting the panel, (which is the containter being affected by the addition), not the frame

imageSpaces[imageCounter].add(lorryImage);
imageSpaces[imageCounter].revalidate();
imageSpaces[imageCounter].repaint();

Diclaimer: This may work as a simple fix, but also note that a component (in this case your JLabel lorryImage) can only have one parent container. The reason the above fix still works is because you don't revalidate and repaint the previous panel, the label was added to. So you may want to think about doing it correctly, and adding a new JLabel to each panel.

if (e.getSource() == addImage) {
    JLabel lorryImage = new JLabel(lorryPicture);
    imageSpaces[imageCounter].add(lorryImage);
    imageSpaces[imageCounter].revalidate();
    imageSpaces[imageCounter].repaint();
    imageCounter++;
}

Disclaimer 2: You should add a check, to only add a label if the count is less than the array length, as to avoid the ArrayIndexOutOfBoundsException


Side Notes

  • Swing apps should be run from the Event Dispatch Thread (EDT). You can do this by wrapping the code in the main in a SwingUtilities.invokeLater(...). See more at Initial Threads

  • You could also just use a JLabel and call setIcon, instead of using a JPanel

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top