自定义 JPanel 大小始终为 0

问题描述

我一直试图了解这里发生的事情很长一段时间,但我还没有找到正确的答案。

我正在尝试从头开始创建一个 JPanel;为此,我定义了一个组布局,然后相应地插入了相应的组件。

问题是,一旦插入了组件,并定义了它们的大小,JPanel 将两个大小(宽度和高度)保持为零值。即使在屏幕上显示(没有错误)之后。

public class PanelPelicula extends JPanel {

Pelicula pelicula;
JTextArea titulo;
JTextArea descripcion;
JLabel imagen;
int escalado = 40;
int escaladoX = escalado * 5;
int escaladoY = escalado * 7;

public PanelPelicula(Pelicula pelicula) {
    super();
    this.pelicula = pelicula;
    inicializar();
}

private void inicializar() {

    titulo = new JTextArea();
    descripcion = new JTextArea();
    imagen = new JLabel();

    titulo.setLineWrap(true);
    titulo.setWrapStyleWord(true);
    titulo.setopaque(false);
    titulo.setEditable(false);
    titulo.setFont(new Font("Malgun Gothic",1,14));
    titulo.setForeground(new Color(255,255,255));
    titulo.setText(pelicula.getTitulo());

    descripcion.setLineWrap(true);
    descripcion.setWrapStyleWord(true);
    descripcion.setopaque(false);
    descripcion.setEditable(false);
    descripcion.setFont(new Font("Malgun Gothic",14));
    descripcion.setForeground(new Color(150,150,150));
    String generos = "(";
    for (String genero : pelicula.getGeneros()) {
        generos += genero + ",";
    }
    generos = generos.substring(0,generos.length() - 2) + ")";
    descripcion.setText(generos);

    imagen.setPreferredSize(new Dimension(escaladoX,escaladoY));
    imagen.setopaque(true);
    imagen.setBackground(new Color(33,33,33));
    try {
        String poster = pelicula.getPoster();
        if (!poster.equals("")) {
            URL urlPoster = new URL(poster);
            ImageIcon icono = new ImageIcon(ImageIO.read(urlPoster).getScaledInstance(escaladoX,escaladoY,2));
            imagen.setIcon(icono);
        }
    } catch (MalformedURLException ex) {
        Logger.getLogger(PanelPelicula.class.getName()).log(Level.SEVERE,null,ex);
    } catch (IOException ex) {
        Logger.getLogger(PanelPelicula.class.getName()).log(Level.SEVERE,ex);
    }

    this.setopaque(false);
    GroupLayout layout = new GroupLayout(this);
    this.setLayout(layout);

    layout.setHorizontalGroup(
            layout.createParallelGroup()
                    .addComponent(imagen,GroupLayout.PREFERRED_SIZE,GroupLayout.DEFAULT_SIZE,GroupLayout.PREFERRED_SIZE)
                    .addComponent(titulo,Short.MAX_VALUE)
                    .addComponent(descripcion,Short.MAX_VALUE)
    );

    layout.setVerticalGroup(
            layout.createSequentialGroup()
                    .addComponent(imagen,GroupLayout.PREFERRED_SIZE)
                    .addGap(10,10,10)
                    .addComponent(titulo,GroupLayout.PREFERRED_SIZE)
                    .addGap(4,4,4)
                    .addComponent(descripcion,Short.MAX_VALUE)
    );

    System.out.println(getSize());
}

}

解决方法

一旦面板可见,它就不会定义其大小。

Swing 组件默认可见,顶级容器除外。

正如我在评论中所说的,面板由布局管理器指定大小。

如果您在视口中向面板动态添加面板,那么基本逻辑是:

panel.add(...);
panel.revalidate(); // to invoke the layout manager

SwingUtilities.invokeLater( () -> 
{
    JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
    horizontal.setValue( horizontal.getMaximum() );
});

invokeLater() 将代码添加到 EDT 的末尾,以便它可以在布局完成并计算所有尺寸值后执行。