4 Layouts¶
Paneles¶
La clase Panel
es la clase más simple de los contenedores de componentes gráficos. Su uso permite que las aplicaciones puedan usar multiples layouts. Permite que cada contenedor pueda tener su propio esquema de fuentes, colores, zona de diálogo, etc.
public class Panels {
public void show() {
Panel panel = new Panel();
Button button = new Button("Panel button");
Label label = new Label("Label text");
panel.add(button);
panel.add(label);
Frame frame = new Frame("Mi panel");
frame.add(panel);
frame.setSize(1000, 1000);
frame.setVisible(true);
}
public static void main(String[] args) {
new Panels().show();
}
}
El método setLayout(layout)
nos permite indicar de que forma se disponen los elementos.
Layouts manager¶
Los layouts managers o manejadores de composición permiten controlar la disposición de los diversos componentes dentro de un contenedor, es decir, especifican que distribución tendrán los componentes a la hora de colocarlos sobre un contenedor. Java dispone de varios como: BorderLayout
, GridLayout
, FlowLayout
, CardLayout
, GridBagLayout
, etc.
¿Por qué Java proporciona estos esquemas predefinidos de disposición de componentes? La razón es simple: imaginemos que deseamos agrupar objetos de distinto tamaño en celdas de una rejilla virtual: si confiados en nuestro conocimiento de un sistema gráfico determinado, y codificamos a mano tal disposición, deberemos prever el redimensionamiento de la ventana, su repintado cuando sea cubierto por otra ventana, etc., además de todas las cuestiones relacionadas con un posible cambio de plataforma (uno nunca sabe a donde van a ir a parar nuestras ventanas).
Sigamos imaginando, ahora, que un hábil equipo de desarrollo ha previsto las disposiciones gráficas más usadas y ha creado un gestor para cada una de tales configuraciones, que se ocupará, de forma transparente para nosotros, de todas esas cuitas de formatos. Bien, pues estos gestores son instancias de las distintas clases derivadas de Layout Manager y que se utilizan en los contenedores de nuestras aplicaciones.
Los Layouts liberan al programador de tener que preocuparse de dónde ubicar cada uno de los componentes cuando una ventana es redimensionada o cuando una ventana es refrescada o cuando una ventana es llevada a una plataforma que maneja un sistema de coordenadas diferente.
FlowLayout¶
Es el layout más simple y el que se utiliza por defecto en los paneles. Los componentes añadidos se encadenan en forma de lista horizontal, de izquierda a derecha.
Existen varias formas de crear un FlowLayout
:
FlowLayout(int align, int hgap, int vgap)
: Crea unFlowLayout
especificando el alineamiento de los elementos, y el espaciado horizontal (hgap) y vertical (vgap). El valor del align puede ser: -0
para la izquierda (se puede usar la constanteLEFT
). -1
para centrado (se puede usar la constanteCENTRE
). -2
para la derecha (se puede usar la constanteRIGHT
) -3
para posicionarse al principio del elemento. Esto depende de la orientación del componente si estamos ante una disposición de izquierda a derecha se posicionaran a la izquierda, si no a la derecha. Se puede usar la constanteLEADING
. -4
para posicionarse al final del elemento. Esto depende de la orientación del componente si estamos ante una disposición de izquierda a derecha se posicionará a la derecha, si no a la izquierda. Se puede usar la constanteTRAILING
.FlowLayout(int align)
: Crea unFlowLayout
con el alineamiento especificado, y con un espacio por defecto de 5, tanto vertical como horizontal.FlowLayout()
: Crea unaFlowLayout
centrado y con espaciado vertical y horizontal de 5, por defecto.
Existen también los getters y setters de dichas propiedades. Además del método setAlignOnBaseline(boolean b)
que permite alinear los elementos según su baseline.
public class FlowLayouts {
public void show() {
Frame frame = new Frame();
Panel panel = new Panel();
LayoutManager flowLayout = new FlowLayout(FlowLayout.CENTER, 10, 10);
Component button = new Button("Button");
Component other = new Button("Other");
Component third = new Button("third");
panel.setLayout(flowLayout);
panel.add(button);
panel.add(other);
panel.add(third);
frame.setSize(1000, 1000);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new FlowLayouts().show();
}
}
BorderLayout¶
La composición BorderLayout
proporciona un esquema más complejo de colocación de los componente en un panel. La composición utiliza cinco zonas para colocar los componentes sobre ellas: norte, sur, este, oeste y centro.
Para poder añadir cada componente, en alguna de dichas direcciones se debe usar la sobrecarga del método add(String name, Component component)
, siendo el valor de name el nombre de la posición del elemento.
Se puede usar indicar el espacio vertical y horizontal haciendo uso del constructor que los recoge: BorderLayout(int vgap, int hgap)
; o con los setters necesarios: setVgap()
para vertical y setHgap()
para horizontal.
public class BorderLayouts {
public void show(){
Frame frame = new Frame();
Panel panel = new Panel();
LayoutManager borderLayout = new BorderLayout();
Button button1 = new Button("North");
Button button2 = new Button("South");
Button button3 = new Button("West");
Button button4 = new Button("East");
Button button5 = new Button("Center");
panel.setLayout(borderLayout);
panel.add("North", button1);
panel.add("South", button2);
panel.add("West", button3);
panel.add("East", button4);
panel.add("Center", button5);
frame.add(panel);
frame.setSize(1000, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new BorderLayouts().show();
}
}
GridLayout¶
La composición GridLayout
proporciona una gran flexibilidad para situar componentes. El layout crea con un número de filas y columnas y los componentes van dentro de las celdas de la tabla así definida.
Todos los componentes comprendido en el layout tienen el mismo tamaño. Si el número de filas es menor que el número de componentes a añadir, omite el valor dado para el número de columna y añade las columnas necesarias para abarcar el número de componentes.
El constructor tiene varias sobrecargas:
GridLayout(int rows, int cols, hgap, vgap)
: crea unGridLayout
definiendo el número de filas y columnas, así como el espaciado vertical y horizontal. El número de filas o el de columnas no puede ser 0 (se lanza unIllegalArgumentException
), aunque uno de ellos sí.GridLayout(int rows, int cols)
: Crea unGridLayout
con el número de filas y columnas. Por defecto, el espaciado, tanto horizontal como vertical, queda en 0.GridLayout()
: Crea unGridLayout
con una fila y ninguna columna.
public class GridLayouts {
public void show() {
Frame frame = new Frame();
Panel panel = new Panel();
LayoutManager borderLayout = new GridLayout(3, 2);
Button button1 = new Button("1");
Button button2 = new Button("2");
Button button3 = new Button("3");
Button button4 = new Button("4");
Button button5 = new Button("5");
Button button6 = new Button("6");
panel.setLayout(borderLayout);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);
frame.add(panel);
frame.setSize(1000, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new GridLayouts().show();
}
}
CardLayout¶
Este tipo de composición es usado cuando se necesita una zona de la ventaja que permita colocar distintos componentes en cada momento. Este layout suele ir asociado con un Choice
, de tal modo que cada selección determina el panel que se presentará.
public class CardLayouts {
private final static String PANEL_BUTTON = "Panel con botones";
private final static String PANEL_TEXT = "Panel con campo de texto";
public void show() {
Frame frame = new Frame();
Panel parent = new Panel();
Panel card = new Panel();
Panel panel = new Panel();
LayoutManager borderLayout = new BorderLayout();
LayoutManager cardLayout = new CardLayout();
Choice choice = new Choice();
choice.addItem(PANEL_BUTTON);
choice.addItem(PANEL_TEXT);
panel.add(choice);
parent.setLayout(borderLayout);
parent.add("North", panel);
card.setLayout(cardLayout);
Panel child1 = new Panel();
child1.add(new Button("Button 1"));
child1.add(new Button("Button 2"));
child1.add(new Button("Button 3"));
Panel child2 = new Panel();
child2.add(new TextField("Texto", 20));
card.add(PANEL_BUTTON, child1);
card.add(PANEL_TEXT, child2);
parent.add("Center", card);
new CardLayout().show(card, PANEL_TEXT);
new CardLayout().show(card, PANEL_BUTTON);
frame.add(parent);
frame.setSize(1000, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new CardLayouts().show();
}
}
De esta manera, puede pasar de esto:
A esto:
Layout personalizado¶
Para poder crear un layout personalizada es necesario implementar la interfaz LayoutManager
y sobrescribir sus métodos:
void addLayoutComponent(String name, Component component)
. Añade el componente a la posición nombrada.void removeLayoutComponent(Component component)
. Elimina el componente del layout.Dimension preferredLayoutSize(Container parent)
. Calcula el tamaño preferido para el especificado container.Dimension miniumLayoutSize(Container parent)
. Calcula el tamaño mínimo para el especificado container.void layoutContainer(Container parent)
. Establece el especificado container.
En el siguiente ejemplo, se desarrolla un layout que permite colocar los componentes en posiciones absolutas del panel que contenga a este layout:
public class CustomLayout implements LayoutManager {
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
Insets insets = parent.getInsets();
int num = parent.getComponentCount();
int width = 0;
int height = 0;
for (int i = 0; i < num; i++) {
Component component = parent.getComponent(i);
Dimension d = component.getPreferredSize();
Point p = component.getLocation();
if((p.x + d.width) > width){
width = p.x + d.width;
}
if((p.y + d.height) > height){
height = p.y + d.height;
}
}
return new Dimension(insets.left + insets.right + width, insets.top + insets.bottom + height);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
int num = parent.getComponentCount();
for (int i = 0; i < num; i++) {
Component component = parent.getComponent(i);
Dimension d = component.getPreferredSize();
component.setSize(d.width, d.height);
}
}
}
public class CustomLayouts {
public void show() {
Frame frame = new Frame();
Panel panel = new Panel();
Button button1 = new Button("Aceptar");
Button button2 = new Button("Abrir");
Button button3 = new Button("Cerrar");
Label label = new Label("Texto");
TextField textField = new TextField("", 20);
panel.setLayout(new CustomLayout());
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(label);
panel.add(textField);
button1.setLocation(0, 10);
button2.setLocation(70, 10);
button3.setLocation(30, 40);
label.setLocation(75,70);
textField.setLocation(120, 70);
frame.setSize(500, 500);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new CustomLayouts().show();
}
}
Canvas¶
Un lienzo es una parte de nuestra UI donde se le permite a los usuarios realizar pintadas. La clase Canvas
representa un lienzo y sus características principales son:
- Permite dibujar directamente en el componente utilizando los métodos de la clase
Graphic
. - Puede manejar eventos del ratón y teclado para interactividad.
- Se puede añadir contenedor de AWT como
Frame
oPanel
, etc.
public class CanvasExample {
public void show() {
Canvas canvas = new Canvas();
Panel panel = new Panel();
panel.add(canvas);
Frame frame = new Frame();
frame.add(panel);
frame.setSize(500, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new CanvasExample().show();
}
}
Proyecto Layout¶
En el siguiente proyecto, se va a desarrollar una aplicación Ui como la siguiente:
public class LayoutProject {
private static class MyCanvas extends Canvas{
@Override
public void paint(Graphics g) {
int w = getSize().width;
int h = getSize().height;
g.drawRect(0, 0, w-1, h-1);
g.drawString("Canvas", (w-g.getFontMetrics().stringWidth("Canvas"))/2, 10);
}
}
public void show() {
Panel panel = createPanel();
Frame frame = new Frame();
frame.setSize(1000, 1000);
frame.add(panel);
frame.setVisible(true);
}
private Panel createPanel() {
Panel panel = new Panel(); // Parent
Panel start = new Panel(); // Left
Panel end = new Panel(); // Right
Panel buttons = new Panel(); // Buttons panel
Panel canvasPanel = new Panel();
start.setLayout(new BorderLayout());
end.setLayout(new BorderLayout());
canvasPanel.setLayout(new BorderLayout());
canvasPanel.setBounds(1, 1, 200, 20);
printStart(start);
printCenter(buttons);
printCanva(canvasPanel);
printEnd(end);
start.add("East", buttons);
start.add("South", canvasPanel);
panel.add(start);
panel.add(end);
return panel;
}
private void printEnd(Panel panel) {
Label label = new Label("Editor");
TextArea textField = new TextArea("Aquí se puede escribir", 8, 30);
panel.add("North", label);
panel.add("South", textField);
}
private void printCenter(Panel panel) {
Button deleteButton = new Button("Borrar");
Button printButton = new Button("Imprimir");
Choice figures = new Choice();
figures.addItem("Cuadrado");
figures.addItem("Circulo");
figures.addItem("Triángulo");
Checkbox checkbox = new Checkbox("Relleno");
panel.add(deleteButton);
panel.add(printButton);
panel.add(figures);
panel.add(checkbox);
}
private void printCanva(Panel panel) {
Label pencilLabel = new Label("Lápiz");
TextField textField = new TextField("1", 8);
Scrollbar pencilScrollbar = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, 10);
pencilScrollbar.setBounds(1, 1, 100, 5);
panel.add("North", pencilLabel);
panel.add("East", textField);
panel.add("Center", pencilScrollbar);
}
private void printStart(Panel panel) {
List colors = new List(6, false);
colors.add("Rojo");
colors.add("Naranja");
colors.add("Amarillo");
colors.add("Verde");
colors.add("Azul");
colors.add("Morado");
colors.add("Negro");
colors.add("Blanco");
panel.add("West", colors);
Canvas canvas = new MyCanvas();
canvas.setBounds(0,0, 100, 100);
panel.add("Center", canvas);
}
public static void main(String[] args) {
new LayoutProject().show();
}
}