JScrollPane + FlowLayout = Bug

1 resposta
M

Bom dia pessoal, estou com um problema chato que não consigo solucionar… resolvi então ver se alguém por aqui me da uma luz.
Eu criei um JPanel e adicionei nele aproximadamente 100 JLabels(ícones) dentro dele. Setei este panel como FlowLayout e depois joguei dentro de um JScrollPane.
O problema é que o scroll não funciona.
Pesquisando na internet encontrei que o método getPreferedSize do FlowLayout não funciona como deveria.
pesquisando mais um pouco encontrei um kra que criou um Flowlayout modificado. Ele funciona, mas até calcular a posição correta dos componentes ele leva aproximadamente 5 segundos, e neste tempo ele fica realocando as posições dos JLabels.

Vou dar um exemplo para vocês executarem ae.

Em um JFrame simples:

initComponents();
        setLayout(new BorderLayout());
        JPanel painelLabels = new JPanel();
        for (int i = 0; i < 100; i++) {
            JLabel jl = new JLabel("|" + i + "|");
            jl.setPreferredSize(new Dimension(32, 32));
            jl.setMinimumSize(new Dimension(32, 32));
            painelLabels.add(jl);
        }

        painelLabels.setLayout(new ModifiedFlowLayout(ModifiedFlowLayout.LEFT));

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewportView(painelLabels);
        add(scrollPane, BorderLayout.CENTER);

agora a classe ModifiedFlowLayout:

package geral;

import java.awt.*;

/**
 * A modified version of FlowLayout that allows containers using this
 * Layout to behave in a reasonable manner when placed inside a
 * JScrollPane

 * @author Babu Kalakrishnan
 * Fonte: http://www.javakb.com/Uwe/Forum.aspx/java-gui/1904/Flowlayout-JPanel-and-JScrollPane-Scrolling-vertically-impossible
 */
public class ModifiedFlowLayout extends FlowLayout {

    public ModifiedFlowLayout() {
        super();
    }

    public ModifiedFlowLayout(int align) {
        super(align);
    }

    public ModifiedFlowLayout(int align, int hgap, int vgap) {
        super(align, hgap, vgap);
    }

    public Dimension minimumLayoutSize(Container target) {
        return computeSize(target, false);
    }

    public Dimension preferredLayoutSize(Container target) {
        return computeSize(target, true);
    }

    private Dimension computeSize(Container target, boolean minimum) {
        synchronized (target.getTreeLock()) {
            int hgap = getHgap();
            int vgap = getVgap();
            int w = target.getWidth();
            
            // Let this behave like a regular FlowLayout (single row)
            // if the container hasn't been assigned any size yet
            if (w == 0) {
                w = Integer.MAX_VALUE;
            }

            Insets insets = target.getInsets();
            if (insets == null) {
                insets = new Insets(0, 0, 0, 0);
            }
            int reqdWidth = 0;

            int maxwidth = w - (insets.left + insets.right + hgap * 2);
            int n = target.getComponentCount();
            int x = 0;
            int y = insets.top;
            int rowHeight = 0;

            for (int i = 0; i < n; i++) {
                Component c = target.getComponent(i);
                if (c.isVisible()) {
                    Dimension d =
                            minimum ? c.getMinimumSize()
                            : c.getPreferredSize();
                    if ((x == 0) || ((x + d.width) <= maxwidth)) {
                        if (x > 0) {
                            x += hgap;
                        }
                        x += d.width;
                        rowHeight = Math.max(rowHeight, d.height);
                    } else {
                        x = d.width;
                        y += vgap + rowHeight;
                        rowHeight = d.height;
                    }
                    reqdWidth = Math.max(reqdWidth, x);
                }
            }
            y += rowHeight;
            return new Dimension(reqdWidth + insets.left + insets.right, y);
        }
    }
}

sugestões?
vlw

1 Resposta

M

Galera o que fiz foi o seguinte(POG)…
iniciei o JPanel, joguei ele na tela como visible(false) e passei o JPanel para uma Thread,
essa Thread espera 1,5 segundos (tempo suficiente para o layout se ajustar) e depois da um jpanel.setVisible(true);

assim quando o usuário abre a janela ele vê um panel em branco e logo ele é carregado…

não é a solução ideal mas já ajuda um pouco, alguém tem alguma idéia do que pode ser feito?

abraço

Criado 26 de janeiro de 2011
Ultima resposta 26 de jan. de 2011
Respostas 1
Participantes 1