Interfaces Tema 5
MigLayout
MigLayout es el layout que usaremos para todo, también en el proyecto final. No viene con Java (es una de las librerías de Preparar el ordenador), pero hace en un solo panel lo que con los layouts clásicos necesita varios anidados.
La idea: una rejilla#
MigLayout coloca los componentes en una rejilla de filas y columnas, como una tabla. Cada add(…) ocupa la celda siguiente, y tú decides cómo es cada columna:
Se configura con tres textos al crearlo:
new MigLayout("wrap 2, insets 20", "[right][grow, fill]", "")
// └ 1. el panel ┘ └ 2. las columnas ┘ └ 3. las filas| Texto | Qué dice | En el ejemplo |
|---|---|---|
| 1. Del panel | Reglas generales | wrap 2: salta de fila cada 2 componentes; insets 20: 20 px de margen |
| 2. De las columnas | Una pareja de corchetes […] por columna, con sus reglas | [right]: la primera alineada a la derecha; [grow, fill]: la segunda crece y estira lo que tiene |
| 3. De las filas | Igual, para las filas | "": nada especial |
Y cada componente puede llevar sus propias reglas, como segundo dato del add: panel.add(boton, "span 2").
Un formulario#
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;
import net.miginfocom.swing.MigLayout;
public class FormularioMig {
public static void main(String[] args) {
FlatLightLaf.setup();
SwingUtilities.invokeLater(() -> {
JFrame ventana = new JFrame("Nuevo alumno");
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 2 columnas: la primera alineada a la derecha, la segunda crece
JPanel panel = new JPanel(new MigLayout("wrap 2, insets 20", "[right][grow, fill]"));
panel.add(new JLabel("Nombre"));
panel.add(new JTextField());
panel.add(new JLabel("Edad"));
panel.add(new JSpinner(new SpinnerNumberModel(16, 6, 99, 1)), "growx 0");
panel.add(new JLabel("Nivel"));
panel.add(new JComboBox<>(new String[] {"Junior", "Senior", "Master", "DEV"}));
panel.add(new JLabel("Observaciones"), "top");
panel.add(new JScrollPane(new JTextArea(4, 20)));
panel.add(new JButton("Cancelar"), "span 2, split 2, align right");
panel.add(new JButton("Guardar"));
ventana.add(panel);
ventana.setSize(460, 330);
ventana.setLocationRelativeTo(null);
ventana.setVisible(true);
});
}
}
Fíjate en tres detalles:
| Código | Qué consigue |
|---|---|
"growx 0" en el JSpinner | Que el número no se estire a todo el ancho, aunque la columna sea fill |
"top" en «Observaciones» | Que la etiqueta quede arriba, a la altura de la primera línea del texto, y no centrada |
"span 2, split 2, align right" en Cancelar | Que la última fila ocupe las 2 columnas (span 2), que en esa celda quepan 2 botones (split 2) y que vayan a la derecha |
Consejo
Si no entiendes por qué algo sale donde sale, añade debug a las reglas del panel: new MigLayout("wrap 2, insets 20, debug", …). MigLayout dibuja las celdas con líneas de colores:

Un panel de tarjetas#
Con lo mismo se hacen las pantallas de un dashboard, como el del proyecto final: cuatro columnas iguales, y cada tarjeta dice cuántas ocupa.
import java.awt.Color;
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;
import net.miginfocom.swing.MigLayout;
public class PanelMig {
public static void main(String[] args) {
FlatLightLaf.setup();
SwingUtilities.invokeLater(() -> {
JFrame ventana = new JFrame("Panel de la academia");
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 4 columnas iguales (sg = mismo tamaño) que crecen con la ventana
JPanel panel = new JPanel(new MigLayout("insets 16, gap 12",
"[grow, fill, sg][grow, fill, sg][grow, fill, sg][grow, fill, sg]",
"[][grow, fill]"));
panel.add(tarjeta("Alumnos", "128"));
panel.add(tarjeta("Matrículas", "34"));
panel.add(tarjeta("Cursos", "6"));
panel.add(tarjeta("Media", "7,4"), "wrap");
panel.add(tarjeta("Gráfica", "(ocupa 3 columnas)"), "span 3");
panel.add(tarjeta("Avisos", "(1 columna)"));
ventana.add(panel);
ventana.setSize(720, 360);
ventana.setLocationRelativeTo(null);
ventana.setVisible(true);
});
}
// Una "tarjeta": un panel con un título pequeño y un dato grande
static JPanel tarjeta(String titulo, String dato) {
JPanel t = new JPanel(new MigLayout("wrap, insets 14"));
t.setBackground(Color.WHITE);
t.setBorder(BorderFactory.createLineBorder(new Color(0xDCE4EE)));
JLabel valor = new JLabel(dato);
valor.setFont(valor.getFont().deriveFont(20f));
t.add(new JLabel(titulo));
t.add(valor);
return t;
}
}
Las tarjetas son a su vez JPanel con su propio MigLayout: un panel dentro de otro, pero ahora cada uno con muy poco código.
Consejo
Todas las reglas, ordenadas por lo que quieres conseguir y con un ejemplo de cada una, están en la hoja de consulta de MigLayout. Tenla abierta mientras programas.
Errores frecuentes#
| Mensaje o síntoma | Qué significa | Cómo se arregla |
|---|---|---|
cannot find symbol en MigLayout | Falta el import o la librería | import net.miginfocom.swing.MigLayout;, y los dos .jar en lib |
IllegalArgumentException: Error parsing Constraint: 'grwox' | Una regla mal escrita (aquí, grwox en vez de growx). Salta al ejecutar, no al compilar | Corrige la palabra que dice el mensaje |
| Todo sale en una sola fila | Falta wrap, en el panel (wrap 2) o en el último componente de cada fila | Añade el wrap |
| Los campos no se estiran al agrandar la ventana | La columna no tiene grow y fill | "[right][grow, fill]" |
| No entiendes por qué algo sale donde sale | — | Añade debug al panel y mira las celdas |