将 2 个或更多组件添加到 JPanel 时组件消失

Components disappear when 2 or more are added to a JPanel

我创建了一个 class SliderPanel 允许用户使用 JSlider 旋转图片和 return 代表所选的 int滑块上的值。该对象继承自 JPanel,因此当我向主 JPanel(creationPanel)添加两个或更多 SliderPanels 时,图片似乎从 GUI 中消失了。是否有解决此问题的方法,我已尝试更改为绝对布局、嵌套面板和调整大小。

这是 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;
    }
}

这里是 Window class 面板被添加到 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;
    }
}

提前致谢!

PS:这是我上传的图片的链接:

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
private static JLabel[] imagesArray;

您正在为 JLabel 组件创建静态数组。

稍后在我看来您试图将数组中的 JLabel 添加到您的面板:

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

问题是 Swing 组件只能有一个父组件。

因此,通过将 JLabel 添加到第二个面板,您可以将其从第一个面板中删除。

不要保留 JLabel 的静态数组。

而是保留 ImageIcon 的静态数组。一个图标可以被多个组件共享。

然后,当您想要将标签添加到面板时,您可以使用 ImageIcon 创建一个新的 JLabel。