javaswinguser-interfacejpaneljslider

Components disappear when 2 or more are added to a JPanel


I have created a class SliderPanel that allows a user to use a JSlider to rotate a picture and return an int representing the selected value on the slider. This object inherits from JPanel, so when I add two or more SliderPanels to the main JPanel (creationPanel), it appears that the pictures disappear from the GUI. Is there a work around for this, I have tried changing to an absolute layout, nesting panels, and resizing.

Here is the code for the SliderPanel:

public class SliderPanel extends JPanel
{
    private JSlider slider;
    private JLabel[] labelsArray;
    private static final GridBagConstraints gbc = new GridBagConstraints();
    private int selectedValue = 5;
    private boolean isImgVisible;
    
    /**
     * Constructor which creates the JPanel and manages the changing of the 
     * JSlider.
     * 
     * @param headerTitle The title of the Panel.
     * @param window The Window object to retrieve the images from.
     */
    public SliderPanel(String headerTitle, Window window)
    {
        setSize(new Dimension(300, 300));
        
        labelsArray = window.getImages();
        
        setLayout(new GridBagLayout());
        
        // Create a header for the label slider and add it to the panel.
        JLabel headerLabel = new JLabel("<HTML><U>" + headerTitle + 
                "</U></HTML>");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.CENTER;
        add(headerLabel, gbc);
        
        Hashtable labels = new Hashtable();
        for (int i = 0; i < 12; i++)
            labels.put(i, new JLabel(String.valueOf(i)));
        
        JPanel sliderAndImgPanel = new JPanel(new GridBagLayout());
        JPanel imgPanel = new JPanel();
        sliderAndImgPanel.setSize(new Dimension(200, 200));
        
        slider = new JSlider(0, 10, 5);
        slider.setLabelTable(labels);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);
        slider.addChangeListener((ChangeEvent e) -> {
            selectedValue = ((JSlider) e.getSource()).getValue();
            System.out.println(selectedValue);
            
            if (isImgVisible)
            {
                System.out.println("in");
                sliderAndImgPanel.remove(imgPanel);
                imgPanel.removeAll();
            }
            
            validate();
            repaint();
            
            JLabel pic = labelsArray[selectedValue];
            pic.setPreferredSize(new Dimension(150, 150));
            imgPanel.add(pic);
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.CENTER;
            sliderAndImgPanel.add(imgPanel, gbc);
            isImgVisible = true;
            validate();
            window.validate();
        });
        
        JLabel pic = labelsArray[5];
        pic.setPreferredSize(new Dimension(150, 150));
        imgPanel.add(pic);
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.CENTER;
        sliderAndImgPanel.add(imgPanel, gbc);
        sliderAndImgPanel.validate();
        
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.CENTER;
        sliderAndImgPanel.add(slider, gbc);
        
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.CENTER;
        add(sliderAndImgPanel, gbc);
    }
    
    /**
     * This method returns the value selected on the JSlider.
     * 
     * @return The selected value. [0, 10] 
     */
    public int getSelectedValue()
    {
        return selectedValue;
    }
}

And here is the Window class where the panels get added to the JFrame:

import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Window extends JFrame
{
    private static JLabel[] imagesArray;
    
    public static void main(String[] args)
    {
        new Window();
    }
    
    public Window()
    {
        super("Testing");
        
        setLayout(new GridLayout(2,1,5,5));
        setSize(1000, 700);
        setVisible(true);
        
        imagesArray = loadImages();
        
        add(new SliderPanel("test 1", this));
        add(new SliderPanel("test 2", this));
        
    }
    
    //  Accessor method.
    public static JLabel[] getImages()
    {
        return imagesArray;
    }
    
    // Loads images from project directory.
    private static JLabel[] loadImages()
    {
        JLabel[] array = new JLabel[11];

        // Load each image into the array.
        for (int i = 0; i < 11; i++)
        {
            try
            {
                BufferedImage newImg = ImageIO.read(new File(i + ".png"));
                array[i] = new JLabel(new ImageIcon(newImg));
            } catch (IOException ex)
            {
                System.out.println("Exception: " + i);
            }
        }

        return array;
    }
}

Thanks in advance!

PS: Here are the links to the images I uploaded:

https://i.imgur.com/BvIehj5.png, 
https://i.imgur.com/f527RdK.png,
https://i.imgur.com/98mgTHr.png,
https://i.imgur.com/Jsqm08U.png,
https://i.imgur.com/0pHTDgE.png,
https://i.imgur.com/TvtEiFm.png,
https://i.imgur.com/VeEDFfn.png,
https://i.imgur.com/3rp59Oz.png,
https://i.imgur.com/AjVf9pU.png,
https://i.imgur.com/sqEO7GL.png,
https://i.imgur.com/dXlush6.png

Solution

  • private static JLabel[] imagesArray;
    

    You are creating a static array for a JLabel component.

    Later it looks to me like you attempt to add a JLabel from the array to your panel:

    JLabel pic = labelsArray[selectedValue];
    pic.setPreferredSize(new Dimension(150, 150));
    imgPanel.add(pic);
    

    The problem is a Swing component can only have a single parent.

    So by adding the JLabel to the second panel you remove it from the first panel.

    Don't keep a static array of JLabels.

    Instead keep a static array of ImageIcon. An Icon CAN be shared by multiple components.

    Then when you want to add the label to the panel you create a new JLabel using the ImageIcon.