Originariamente inviato da ZannaZ
Il problema è che il flow layout mi servirebbe proprio in NORTH e SOUTH
Si potrebbe realizzare un layout manager specifico simile al FlowLayout ma che fornisca un preferred height corretto, cioè che metta in conto tutte le "righe" di componenti.
Ed è proprio quello che ho fatto nel mio seguente esempio. Prova a ridimensionare orizzontalmente la finestra e vedrai che i pulsanti fluiscono bene e la parte CENTER si modifica per fare più o meno spazio alla parte NORTH.
codice:
import java.awt.*;
import javax.swing.*;
public class TestFrame extends JFrame {
public TestFrame() {
super ("Test");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
Container contentPane = getContentPane();
JPanel panel = new JPanel(new ExpandableFlowLayout());
for (int i = 1; i <= 12; i++) {
panel.add(new JButton("" + i));
}
contentPane.add(panel, BorderLayout.NORTH);
contentPane.add(new JButton("ABC"), BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame f = new TestFrame();
f.setVisible(true);
}
});
}
}
class ExpandableFlowLayout implements LayoutManager {
private Dimension dimension;
public void addLayoutComponent(String name, Component comp) { /* no, uso getComponents */ }
public void removeLayoutComponent(Component comp) { /* no, uso getComponents */ }
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
public Dimension preferredLayoutSize(Container parent) {
if (dimension == null || dimension.width != parent.getSize().width) {
calcDimension(parent);
}
return dimension;
}
public void layoutContainer(Container parent) {
Component[] components = parent.getComponents();
Dimension parentSize = parent.getSize();
int maxHeight = 0;
int x = 0;
int y = 0;
for (int i = 0; i < components.length; i++) {
Component c = components[i];
if (c.isVisible()) {
Dimension size = c.getPreferredSize();
if (x + size.width > parentSize.width) {
x = 0;
y += maxHeight;
maxHeight = 0;
}
c.setSize(size);
c.setLocation(x, y);
x += size.width;
if (size.height > maxHeight) {
maxHeight = size.height;
}
}
}
dimension = new Dimension(parentSize.width, y + maxHeight);
}
private void calcDimension(Container parent) {
Component[] components = parent.getComponents();
Dimension parentSize = parent.getSize();
int maxHeight = 0;
int x = 0;
int y = 0;
for (int i = 0; i < components.length; i++) {
Component c = components[i];
if (c.isVisible()) {
Dimension size = c.getPreferredSize();
if (x + size.width > parentSize.width) {
x = 0;
y += maxHeight;
maxHeight = 0;
}
x += size.width;
if (size.height > maxHeight) {
maxHeight = size.height;
}
}
}
dimension = new Dimension(parentSize.width, y + maxHeight);
}
}
È molto "grezzo" come layout manager, non gestisce dei hgap/vgap come FlowLayout e nemmeno un alignment. E non prende in considerazione gli "insets" (se presenti) del container. In meno di 100 righe di codice non è che si possa fare granchè ....
Però vedi che è possibile, basterebbe solo avere un po' più di tempo (e voglia) e si potrebbe realizzare un layout manager più completo. Chiaro ... ci sarebbero da fare molti più calcoli e controlli.