Este documneto explora el desarrollo de interfaces gráficas de usuario (GUI) en Java, cubriendo tanto el conjunto de herramientas AWT como el más moderno Swing.
Conjunto de herramientas AWT
Clase Frame
La clase Frame representa una ventana principal. Se puede configurar su visibilidad, tamaño, posición y otras propiedades.
import java.awt.*;
import java.awt.event.*;
public class VentanaBasica {
public static void main(String[] args) {
// Crear una instancia de Frame con título
Frame ventana = new Frame("Mi Ventana Java");
// Hacer la ventana visible
ventana.setVisible(true);
// Definir dimensiones (ancho, alto)
ventana.setSize(400, 400);
// Establecer un color de fondo
ventana.setBackground(new Color(147, 135, 72));
// Posicionar la ventana en la pantalla (x, y)
ventana.setLocation(700, 300);
// Deshabilitar el redimensionamiento por parte del usuario
ventana.setResizable(false);
}
}
Panel
Un Panel es un contenedor que puede ser añadido a un Frame. Permite organizar componentes y manejar sus propios eventos.
import java.awt.*;
import java.awt.event.*;
public class PanelEnFrame {
public static void main(String[] args) {
Frame ventana = new Frame();
Panel panelPrincipal = new Panel();
// Deshabilitar el gestor de layout predeterminado
ventana.setLayout(null);
// Configurar la ventana
ventana.setBounds(300, 300, 500, 500);
ventana.setBackground(new Color(112, 166, 30));
// Configurar el panel relativo a la ventana
panelPrincipal.setBounds(50, 50, 400, 400);
panelPrincipal.setBackground(new Color(159, 125, 54));
// Agregar el panel a la ventana
ventana.add(panelPrincipal);
// Añadir un listener para manejar el cierre de la ventana
ventana.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ventana.setVisible(true);
}
}
Gestores de Layout
FlowLayout (Disposición en flujo)
Organiza los componentes en una fila, con la opción de alinearlos a la izquierda, centro o derecha.
import java.awt.*;
public class EjemploFlowLayout {
public static void main(String[] args) {
Frame ventana = new Frame("FlowLayout Demo");
// Crear componentes
Button btnA = new Button("Botón A");
Button btnB = new Button("Botón B");
Button btnC = new Button("Botón C");
// Asignar el gestor de layout
ventana.setLayout(new FlowLayout(FlowLayout.LEFT));
// Agregar componentes
ventana.add(btnA);
ventana.add(btnB);
ventana.add(btnC);
ventana.setSize(400, 400);
ventana.setVisible(true);
}
}
BorderLayout (Disposición por regiones)
Organiza los componentes en cinco áreas: Norte, Sur, Este, Oeste y Centro.
import java.awt.*;
public class EjemploBorderLayout {
public static void main(String[] args) {
Frame ventana = new Frame("BorderLayout Demo");
Button norte = new Button("Norte");
Button sur = new Button("Sur");
Button este = new Button("Este");
Button oeste = new Button("Oeste");
Button centro = new Button("Centro");
// Añadir componentes a sus regiones específicas
ventana.add(norte, BorderLayout.NORTH);
ventana.add(sur, BorderLayout.SOUTH);
ventana.add(este, BorderLayout.EAST);
ventana.add(oeste, BorderLayout.WEST);
ventana.add(centro, BorderLayout.CENTER);
ventana.setSize(400, 400);
ventana.setVisible(true);
}
}
GridLayout (Disposición en cuadrícula)
Organiza los componentes en una cuadrícula de filas y columnas de igual tamaño.
import java.awt.*;
public class EjemploGridLayout {
public static void main(String[] args) {
Frame ventana = new Frame("GridLayout Demo");
// Crear 6 botones
Button[] botones = new Button[6];
for (int i = 0; i < 6; i++) {
botones[i] = new Button("Botón " + (i + 1));
}
// Definir una cuadrícula de 3x2 con espaciado
ventana.setLayout(new GridLayout(3, 2, 5, 5));
for (Button boton : botones) {
ventana.add(boton);
}
ventana.pack(); // Ajustar tamaño al contenido
ventana.setVisible(true);
}
}
Combinación de Layouts
Es común combinar diferentes gestores de layout y paneles para crear interfaces complejas.
import java.awt.*;
public class LayoutCompuesto {
public static void main(String[] args) {
Frame ventana = new Frame();
ventana.setLayout(new GridLayout(2, 1)); // Dos filas
// Panel superior: BorderLayout con sub-panel GridLayout
Panel panelSuperior = new Panel(new BorderLayout());
Panel centroSuperior = new Panel(new GridLayout(2, 1));
panelSuperior.add(new Button("Izquierda"), BorderLayout.WEST);
panelSuperior.add(new Button("Derecha"), BorderLayout.EAST);
centroSuperior.add(new Button("Centro Arriba"));
centroSuperior.add(new Button("Centro Abajo"));
panelSuperior.add(centroSuperior, BorderLayout.CENTER);
// Panel inferior: BorderLayout con sub-panel GridLayout
Panel panelInferior = new Panel(new BorderLayout());
Panel centroInferior = new Panel(new GridLayout(2, 2));
panelInferior.add(new Button("Izq Inf"), BorderLayout.WEST);
panelInferior.add(new Button("Der Inf"), BorderLayout.EAST);
for (int i = 0; i < 4; i++) {
centroInferior.add(new Button("Botón"));
}
panelInferior.add(centroInferior);
ventana.add(panelSuperior);
ventana.add(panelInferior);
ventana.setSize(500, 500);
ventana.setVisible(true);
}
}
Escucha de Eventos (Event Listening)
Los eventos permiten a la aplicación responder a las acciones del usuario. El patrón ActionListener es común para botones.
import java.awt.*;
import java.awt.event.*;
public class EscuchaEventos {
public static void main(String[] args) {
Frame ventana = new Frame();
Button boton1 = new Button("Botón A");
Button boton2 = new Button("Botón B");
// Establecer un comando de acción para identificar el botón
boton1.setActionCommand("ACCION_BOTON_A");
// Crear e instalar un listener
ActionListener listener = e -> {
System.out.println("Botón presionado: " + e.getActionCommand());
};
boton1.addActionListener(listener);
boton2.addActionListener(listener);
ventana.add(boton1, BorderLayout.NORTH);
ventana.add(boton2, BorderLayout.SOUTH);
// Listener para el cierre de la ventana
ventana.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ventana.setSize(300, 200);
ventana.setVisible(true);
}
}
Eventos de Campo de Texto (TextField)
Los campos de texto generan un evento de acción (ActionEvent) cuando el usuario presiona Enter.
import java.awt.*;
import java.awt.event.*;
public class EventoTexto {
public static void main(String[] args) {
new VentanaConTexto();
}
}
class VentanaConTexto extends Frame {
public VentanaConTexto() {
TextField campoTexto = new TextField(20);
add(campoTexto);
// Listener para el campo de texto
campoTexto.addActionListener(e -> {
TextField fuente = (TextField) e.getSource();
System.out.println("Texto ingresado: " + fuente.getText());
fuente.setText(""); // Limpiar después de la acción
});
// Opcional: caracter de eco para campos de contraseña
campoTexto.setEchoChar('*');
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
pack();
setVisible(true);
}
}
Ejemplo: Calculadora Simple y Optimización con Clases Internas
Un ejemplo que demuestra la organización del código usando clases internas para los listeners.
import java.awt.*;
import java.awt.event.*;
public class Calculadora {
public static void main(String[] args) {
new MarcoCalculadora();
}
}
class MarcoCalculadora extends Frame {
private TextField campoNum1, campoNum2, campoResultado;
public MarcoCalculadora() {
setTitle("Calculadora AWT");
campoNum1 = new TextField(10);
campoNum2 = new TextField(10);
campoResultado = new TextField(15);
campoResultado.setEditable(false);
Label etiqueta = new Label("+");
Button botonCalcular = new Button("=");
// Uso de clase interna para el listener
botonCalcular.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int valor1 = Integer.parseInt(campoNum1.getText());
int valor2 = Integer.parseInt(campoNum2.getText());
campoResultado.setText(String.valueOf(valor1 + valor2));
} catch (NumberFormatException ex) {
campoResultado.setText("Error");
}
campoNum1.setText("");
campoNum2.setText("");
}
});
setLayout(new FlowLayout());
add(campoNum1);
add(etiqueta);
add(campoNum2);
add(botonCalcular);
add(campoResultado);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
pack();
setVisible(true);
}
}
Pintura y Graphics
Se puede sobrescribir el método paint() para dibujar dentro de un componente usando el objeto Graphics.
import java.awt.*;
public class EjemploPintura extends Frame {
public EjemploPintura() {
setSize(600, 400);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
}
@Override
public void paint(Graphics g) {
g.setColor(Color.RED);
g.drawOval(100, 100, 100, 100); // Óvalo vacío
g.setColor(Color.BLUE);
g.fillOval(250, 100, 100, 100); // Óvalo relleno
g.setColor(Color.GREEN);
g.fillRect(400, 100, 100, 100); // Rectángulo relleno
}
public static void main(String[] args) {
new EjemploPintura();
}
}
Escucha de Eventos del Ratón (MouseListener)
Permite capturar clics, movimiento y arrastre del ratón. Se usa un MouseAdapter para simplificar.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class DibujarConRaton extends Frame {
private ArrayList<Point> puntos = new ArrayList<>();
public DibujarConRaton() {
setTitle("Dibujar con el Ratón");
setSize(600, 400);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// Registrar el punto donde se presionó el ratón
puntos.add(new Point(e.getX(), e.getY()));
repaint(); // Solicitar repintado
}
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
setVisible(true);
}
@Override
public void paint(Graphics g) {
// Dibujar todos los puntos registrados
g.setColor(Color.DARK_GRAY);
for (Point p : puntos) {
g.fillOval(p.x - 4, p.y - 4, 8, 8);
}
}
public static void main(String[] args) {
new DibujarConRaton();
}
}
Escucha de Eventos de Teclado (KeyListener)
Captura pulsaciones de teclas. Se usa KeyAdapter para implementar solo los métodos necesarios.
import java.awt.*;
import java.awt.event.*;
public class EventosTeclado extends Frame {
public EventosTeclado() {
setSize(400, 300);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int codigoTecla = e.getKeyCode();
System.out.println("Código de tecla: " + codigoTecla);
// Comparar con constantes de KeyEvent
if (codigoTecla == KeyEvent.VK_UP) {
System.out.println("Flecha Arriba presionada");
} else if (codigoTecla == KeyEvent.VK_SPACE) {
System.out.println("Barra espaciadora presionada");
}
}
});
}
public static void main(String[] args) {
new EventosTeclado();
}
}
Conjunto de herramientas Swing
Swing es una extensión más moderna y rica de AWT, proporcionando componentes con aspecto y comportamiento más consistentes entre plataformas.
JFrame y JPanel
JFrame es la ventana principal en Swing. Para cambiar el color de fondo, se debe acceder a su contentPane.
import javax.swing.*;
import java.awt.*;
public class EjemploJFrame {
public static void main(String[] args) {
JFrame marco = new JFrame("Ventana Swing");
marco.setBounds(100, 100, 600, 400);
// Obtener el panel de contenido para personalizar
Container panelContenido = marco.getContentPane();
panelContenido.setBackground(Color.LIGHT_GRAY);
JLabel etiqueta = new JLabel("¡Hola Swing!");
panelContenido.add(etiqueta, BorderLayout.NORTH);
// Configurar el comportamiento al cerrar
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}
JDialog (Cuadros de Diálogo)
JDialog se utiliza para crear ventanas secundarias, como diálogos modales o modales de aplicación.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DialogoEjemplo {
public static void main(String[] args) {
JFrame marcoPrincipal = new JFrame("Marco Principal");
marcoPrincipal.setSize(400, 300);
marcoPrincipal.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton botonAbrir = new JButton("Abrir Diálogo");
botonAbrir.addActionListener(e -> {
// Crear y mostrar el diálogo
JDialog dialogo = new JDialog(marcoPrincipal, "Mi Diálogo", true);
dialogo.setSize(250, 150);
dialogo.setLocationRelativeTo(marcoPrincipal); // Centrar respecto al padre
dialogo.add(new JLabel("Contenido del diálogo"), BorderLayout.CENTER);
dialogo.setVisible(true);
});
marcoPrincipal.add(botonAbrir, BorderLayout.CENTER);
marcoPrincipal.setVisible(true);
}
}
Etiquetas con Iconos (ImageIcon)
Se pueden mostrar imágenes en etiquetas usando ImageIcon.
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class ImagenEnEtiqueta {
public static void main(String[] args) {
JFrame marco = new JFrame("Imagen");
marco.setSize(500, 400);
JLabel etiqueta = new JLabel();
// Cargar imagen desde recursos (ajustar ruta)
URL urlRecurso = ImagenEnEtiqueta.class.getResource("imagen.png");
if (urlRecurso != null) {
ImageIcon iconoOriginal = new ImageIcon(urlRecurso);
// Escalar la imagen (ej: al 50%)
Image imagenEscalada = iconoOriginal.getImage().getScaledInstance(
iconoOriginal.getIconWidth() / 2,
iconoOriginal.getIconHeight() / 2,
Image.SCALE_SMOOTH
);
etiqueta.setIcon(new ImageIcon(imagenEscalada));
} else {
etiqueta.setText("Imagen no encontrada");
}
etiqueta.setHorizontalAlignment(SwingConstants.CENTER);
marco.add(etiqueta);
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}
JScrollPane (Paneles con Scroll)
Envuelve componentes que pueden exceder el espacio visible, como áreas de texto o listas, proporcionando barras de desplazamiento.
import javax.swing.*;
import java.awt.*;
public class AreaTextoScrollable {
public static void main(String[] args) {
JFrame marco = new JFrame("JScrollPane Demo");
marco.setSize(500, 300);
JTextArea areaTexto = new JTextArea(15, 40);
areaTexto.setText("Este es un texto de ejemplo muy largo...\n".repeat(10));
// Envolver el área de texto en un JScrollPane
JScrollPane panelScroll = new JScrollPane(areaTexto);
// Opcional: política de scroll
panelScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
marco.add(panelScroll);
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}
Botones: RadioButton, CheckBox
Los radio buttons (JRadioButton) permtien selección única dentro de un grupo (ButtonGroup). Los checkboxes (JCheckBox) permiten selección múltiple.
import javax.swing.*;
import java.awt.*;
public class BotonesSeleccion {
public static void main(String[] args) {
JFrame marco = new JFrame("Botones");
marco.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20));
// Grupo de RadioButtons (selección única)
JRadioButton radioA = new JRadioButton("Opción A");
JRadioButton radioB = new JRadioButton("Opción B");
JRadioButton radioC = new JRadioButton("Opción C");
ButtonGroup grupoRadio = new ButtonGroup();
grupoRadio.add(radioA);
grupoRadio.add(radioB);
grupoRadio.add(radioC);
// CheckBoxes (selección múltiple)
JCheckBox check1 = new JCheckBox("Check 1");
JCheckBox check2 = new JCheckBox("Check 2");
JCheckBox check3 = new JCheckBox("Check 3");
marco.add(new JLabel("Selección Única:"));
marco.add(radioA);
marco.add(radioB);
marco.add(radioC);
marco.add(new JLabel("Selección Múltiple:"));
marco.add(check1);
marco.add(check2);
marco.add(check3);
marco.setSize(300, 250);
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}
JComboBox (Cuadros Combinados) y JList (Listas)
JComboBox es un menú desplegable. JList muestra una lista de elementos, frecuentemente dentro de un JScrollPane.
import javax.swing.*;
import java.awt.*;
public class ListasDesplegables {
public static void main(String[] args) {
JFrame marco = new JFrame("Listas");
marco.setLayout(new FlowLayout(FlowLayout.LEFT));
// ComboBox (desplegable)
String[] opciones = {"Rojo", "Verde", "Azul", "Amarillo"};
JComboBox<String> comboColor = new JComboBox<>(opciones);
comboColor.setSelectedIndex(0); // Seleccionar el primero por defecto
// Lista con scroll
String[] nombres = {"Ana", "Carlos", "Beatriz", "David", "Elena", "Fernando"};
JList<String> listaNombres = new JList<>(nombres);
listaNombres.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane panelScrollLista = new JScrollPane(listaNombres);
panelScrollLista.setPreferredSize(new Dimension(150, 100));
marco.add(new JLabel("Color favorito:"));
marco.add(comboColor);
marco.add(Box.createHorizontalStrut(20)); // Espacio
marco.add(new JLabel("Seleccionar nombre:"));
marco.add(panelScrollLista);
marco.setSize(450, 200);
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}
JTextField, JPasswordField, JTextArea
Componentes para la entrada y edición de texto en una o varias líneas.
import javax.swing.*;
import java.awt.*;
public class CamposTexto {
public static void main(String[] args) {
JFrame marco = new JFrame("Campos de Texto");
marco.setLayout(new GridLayout(4, 2, 10, 10));
JTextField campoTexto = new JTextField("Texto editable", 20);
JPasswordField campoClave = new JPasswordField(20);
campoClave.setEchoChar('•'); // Caracter de eco
JTextArea areaTextoMulti = new JTextArea("Área de texto multilínea...", 5, 20);
areaTextoMulti.setLineWrap(true); // Ajuste de línea automático
marco.add(new JLabel("JTextField:"));
marco.add(campoTexto);
marco.add(new JLabel("JPasswordField:"));
marco.add(campoClave);
marco.add(new JLabel("JTextArea (dentro de scroll):"));
marco.add(new JScrollPane(areaTextoMulti));
marco.setSize(400, 300);
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setVisible(true);
}
}