Curso de Java Swing

Componente JFrame en un proyecto

En esta lección aprenderemos cómo crear una ventana básica en Java utilizando la clase JFrame, y también cómo añadirle un componente, como un botón, para comenzar a construir interfaces gráficas de usuario (GUI).

Crear un JFrame

El JFrame es el contenedor principal que utilizaremos para mostrar nuestra interfaz. Vamos a crear un JFrame y configurarlo con las propiedades necesarias para que se muestre correctamente. Este es el código:

JFrame frame = new JFrame("Nombre de la ventana"); // Creamos la ventana con un titulo
frame.setSize(800,600); //le asignamos un tamaño
//frame.setLocation(0,0); //Definimos el origen de coordenadas de la ventana
frame.setLocationRelativeTo(null);//Centra la ventana en la pantalla
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//definimos que pasará cuando pulsemos el botón de cerrar
frame.setVisible(true); //La hacemos visible

Desglosemos el código:

  1. new JFrame(String): Creamos un objeto JFrame con un título especificado.
  2. setSize(int, int): Establecemos el tamaño de la ventana en píxeles.
  3. setLocationRelativeTo(null): Centramos la ventana en la pantalla. Si quisiéramos posicionarla en un lugar específico, podríamos usar setLocation(x, y).
  4. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE): Definimos que el programa terminará al cerrar la ventana.
  5. setVisible(true): Mostramos la ventana.

Crear un componente y añadirlo a la ventana

Una vez que tenemos nuestra ventana, podemos agregarle componentes, como botones, campos de texto, etiquetas, etc. Veamos cómo crear un botón y agregarlo al JFrame:

JButton button = new JButton("Texto boton");
frame.add(button);

Sin haber establecido un layout, el botón se estirará para ocupar toda la pantalla

Para evitar esto, podemos usar un layout, por ejemplo:

frame.setLayout(new FlowLayout());

Si queremos que los componentes se alineen verticalmente, no es posible usando FlowLayout, pero podemos crear una nueva clase llamada VerticalFlowlayout

Algunos componentes

Además de los botones, podemos utilizar otros componentes en nuestras interfaces. A continuación, veremos ejemplos:

JTextArea ciclosTextArea = new JTextArea(15,20);

//Muestra un mensaje no editable
JLabel label = new JLabel("nombre");

//Muestra un cuadro de diálogo con un mensaje
JOptionPane.showMessageDialog(Ventana.this, "Eggs are not supposed to be green.");

Desglosemos los componentes:

  1. JTextArea: Es un área de texto donde el usuario puede escribir varias líneas. Las dimensiones iniciales se definen en filas y columnas.
  2. JLabel: Es una etiqueta para mostrar texto estático, ideal para identificar campos o mostrar mensajes.
  3. JOptionPane.showMessageDialog: Permite mostrar un cuadro de diálogo emergente con un mensaje. Es útil para notificaciones o alertas.

Forma habitual de instanciar una ventana

En proyectos más grandes, es habitual organizar el código creando una clase que extienda JFrame. Así podemos encapsular la configuración de la ventana dentro de una clase específica. Veamos un ejemplo:

public class Main {
public static void main(String[] args) {
Ventana ventana = new Ventana();
ventana.setVisible(true);
}
}
public class Ventana extends JFrame {
public Ventana() {
inicializar();
}
private void inicializar() {
this.setSize(800,600);
}
}

Ventajas de este enfoque:

  • Separa la lógica principal de la configuración de la ventana.
  • Facilita el mantenimiento y la extensión del código.

Componente JButton

Uno de los componentes más utilizados en Swing es el JButton, que permite a los usuarios interactuar con la interfaz mediante clics. Podemos manejar eventos asociados a los botones utilizando ActionListener. Veamos cómo hacerlo:

JButton btn= new JButton("Botón");
btn.addActionListener(this);
...
public void actionPerformed(ActionEvent e) {
if(e.getSource() == this.hacerMagia) {

}else if(e.getSource() == this.altaCurso) {

}
}

En este ejemplo:

  • addActionListener(this): Vincula el botón a un evento.
  • actionPerformed(ActionEvent e): Se ejecuta cada vez que ocurre un evento asociado al botón.

También podemos utilizar una clase anónima para manejar eventos, lo cual es útil si solo queremos asociar lógica rápida a un botón específico:

btn.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		int row = tabla.getSelectedRow();
		listadoCursos.remove(row);
		alimentarTabla();
		System.out.println(row);
	}
});

En este caso:

  • Se elimina un curso de una lista basada en la fila seleccionada en una tabla.
  • Se imprime la fila eliminada por consola.

Layouts

Un layout es el mecanismo que Swing utiliza para organizar los componentes dentro de un contenedor. Existen varios tipos de layouts. Aquí explicamos algunos de los más comunes:

BorderLayout

Es el layout por defecto si no indicamos ninguno. Permite organizar los componentes en cinco regiones: Norte, Sur, Este, Oeste y Centro.

JButton btn1 = new JButton("btn1");
JButton btn2 = new JButton("btn2");
this.add(btn1, BorderLayout.NORTH);
this.add(btn2, BorderLayout.SOUTH);

BoxLayout

Organiza los componentes en una dirección, ya sea vertical u horizontal.

BoxLayout.PAGE_AXIS coloca los elementos verticalmente, de arriba a abajo
this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.PAGE_AXIS));
		
JButton btn1 = new JButton("btn1");
JButton btn2 = new JButton("btn2");
		
this.add(btn1);
this.add(btn2);

Group Layout

Esto es un poco complejo. Para que funcione correctamente tengo que añadir todos los componentes dos veces, una horizontal y otra verticalemente

GroupLayout layout = new GroupLayout(this.getContentPane());
layout.setAutoCreateContainerGaps(true);
layout.setAutoCreateGaps(true);

layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(btn1).addComponent(btn2).addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(btn3).addComponent(btn4)));

layout.setVerticalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(btn1).addComponent(btn2).addComponent(btn3)).addComponent(btn4));


this.setLayout(layout);

Componente JTable

En esta lección, aprenderemos a utilizar el componente JTable en Java para mostrar y manipular datos en formato tabular. Veremos cómo configurar su contenido, personalizar su apariencia, añadir eventos interactivos y materializar opciones como la eliminación de filas.

1. Creación de una JTable básica

Lo primero que hacemos es crear una tabla con datos y columnas predefinidas. En este caso, hemos utilizado un arreglo bidimensional para los datos y un arreglo unidimensional para los nombres de las columnas.

String data[][]={ {"101","Amit","670000"},{"102","Jai","780000"},{"101","Sachin","700000"}};    
// (es posible incrustar código html si lo hacemos dentro de las etiquetas <html>)
String columns[]={"Ciclo","Módulo","<html>Unidad<br>Formativa>","Opcion"};
JTable tabla=new JTable(cursillos,column);
tabla.setBounds(30,40,200,300);
JScrollPane sp=new JScrollPane(tabla);

sp.setPreferredSize(new Dimension(1000, 300));
sp.setMinimumSize(new Dimension(1000,200));

panelGlobal.add(sp);
  • Datos: Representan el contenido que se mostrará en las celdas de la tabla.
  • Columnas: Son los encabezados de cada columna.
  • JScrollPane: Añadimos la tabla dentro de un JScrollPane para permitir el desplazamiento.

2. Cambiar el encabezado de la tabla

Si queremos modificar el encabezado de la tabla después de su creación, podemos obtener el JTableHeader y personalizarlo:

tabla = new JTable();
JTableHeader th = tabla.getTableHeader();
th.setPreferredSize(new Dimension(100, 100));

Aquí hemos cambiado el tamaño del encabezado con setPreferredSize.

3. Ajustar únicamente la altura de la tabla

En ocasiones solo necesitamos ajustar la altura sin cambiar el ancho de la tabla:

JTableHeader th = tabla.getTableHeader();
		
Dimension d = th.getPreferredSize();
d.height = 30;
th.setPreferredSize(d);

Esto nos permite tener control específico sobre el tamaño sin afectar otras dimensiones.

4. Alimentar la tabla sin usar su constructor

También podemos llenar una tabla después de haberla creado usando un modelo de datos (DefaultTableModel):

DefaultTableModel tableModel = new DefaultTableModel(cursillos, columns);
tabla.setModel(tableModel);

5. Alimentando la tabla con un ArrayList

Si trabajamos con colecciones como ArrayList, podemos convertirlas en un arreglo compatible para alimentar la tabla:

String[][] arrayListCursoToMultidimensionalStringArray(ArrayListcursos){
	Iterator<Curso> it = cursos.iterator();
	String [][] cursosArray= new String[cursos.size()][3];
	int i=0;
	while(it.hasNext()) {
		Curso c = it.next();
		String[]curso = {c.getCiclo(), c.getModulo(), c.getUf(), "X"};
		cursosArray[i] =curso; 
		i++;
	}
	return cursosArray;	
}

6. Añadiendo un listener a la tabla

Podemos añadir un MouseListener para interactuar con la tabla, por ejemplo, detectar clics:

JTable jt=new JTable(cursillos,column);   

jt.addMouseListener(new MouseAdapter() {
	public void mousePressed(MouseEvent e) {
		System.out.println("llega");
	}
});

7. Añadir un popup al pulsar sobre una fila

Podemos mostrar un menú contextual (JPopupMenu) al hacer clic derecho sobre una fila:

JPopupMenu popup = new JPopupMenu();
JMenuItem removeItem = new JMenuItem("Eliminar fila");
popup.add(removeItem);

JTable tabla=new JTable(cursillos,column);   

tabla.addMouseListener(new MouseAdapter() {
	public void mousePressed(MouseEvent e) {
		popup.show(jt, e.getX(), e.getY());
	}
});

8. Materializar la opción de borrado

Por último, añadimos funcionalidad al botón de eliminar del menú contextual:

removeItem.addActionListener(new ActionListener() {
	
	@Override
	public void actionPerformed(ActionEvent e) {
		int row = tabla.getSelectedRow();
		System.out.println(row);
	}
});

Tabs

Este componente permite organizar la información en secciones separadas, ofreciendo una navegación sencilla y ordenada para el usuario.

1. Creación de un JTabbedPane con pestañas

JTabbedPane tabbedPane = new JTabbedPane();

tabbedPane.add("Colors", new JPanel());
tabbedPane.add( "Fruits", new JPanel());
tabbedPane.add("Vitamins", new JPanel( ) ) ;
	 
panelGlobal.add(tabbedPane);
  • add(String title, Component component): Permite añadir una pestaña especificando el título y el componente que será su contenido.
  • panelGlobal.add(tabbedPane): Agrega el JTabbedPane al contenedor principal (panelGlobal en este caso).

En este ejemplo, hemos añadido tres pestañas con los títulos Colors, Fruits y Vitamins. Cada pestaña tiene un JPanel vacío como contenido.

2. Modificación dinámica del contenido de una pestaña

Si necesitas actualizar el contenido de una pestaña en tiempo de ejecución, puedes usar el método setComponentAt. Este método permite reemplazar el componente de una pestaña específica.

tabbedPane.setComponentAt(2, panelCursos);

En este caso:

  • 2: Es el índice de la pestaña que queremos modificar (las pestañas están indexadas desde 0).
  • panelCursos: Es el nuevo componente que queremos mostrar en la pestaña con índice 2.

Esto es útil cuando los datos o el diseño de una pestaña cambian según la interacción del usuario o la lógica de la aplicación.

Componente JMenu

Los componentes JMenuBar, JMenu y JMenuItem son elementos son fundamentales para estructurar opciones como «Archivo», «Editar», «Ayuda», entre otras.

1. Creación de la barra de menú

El componente JMenuBar sirve como contenedor principal para los menús. A continuación, agregamos un menú con varias opciones:

JMenuBar menuBar = new JMenuBar();  // Crear la barra de menú
JMenu fileMenu = new JMenu("Archivo");  // Crear un menú llamado "Archivo"

En este caso:

  • JMenuBar: Es la barra que contiene los menús principales.
  • JMenu: Representa un menú desplegable que aparece en la barra de menú.

2. Añadiendo opciones al menú

Para añadir opciones específicas dentro del menú Archivo, usamos el componente JMenuItem:

JMenuItem importarMenuItem = new JMenuItem("Importar");
JMenuItem exportarMenuItem = new JMenuItem("Exportar");

fileMenu.add(importarMenuItem);  // Añadir la opción "Importar"
fileMenu.add(exportarMenuItem);  // Añadir la opción "Exportar"
  • JMenuItem: Representa una opción dentro del menú. En este caso, las opciones son Importar y Exportar.
  • add: Se utiliza para agregar las opciones al menú.

3. Vinculación del menú a la barra y ventana

Una vez configurados el menú y sus opciones, lo añadimos a la barra de menú y, posteriormente, asociamos esta barra a la ventana principal (JFrame):

menuBar.add(fileMenu);  // Añadir el menú "Archivo" a la barra de menú
this.setJMenuBar(menuBar);  // Establecer la barra de menú en la ventana

El método setJMenuBar vincula la barra de menú con la ventana actual.

Cuadro de diálogo para abrir/salvar ficheros

La clase JFileChooser permite acceder a ficheros o carpetasd e nuestro ordenador.

JFileChooser c = new JFileChooser();                        
int rVal = c.showOpenDialog(Ventana.this);
if (rVal == JFileChooser.APPROVE_OPTION) {
      System.out.println(c.getSelectedFile().getName());
      System.out.println(c.getCurrentDirectory().toString());
}
if (rVal == JFileChooser.CANCEL_OPTION) {
      System.out.println("Pulsaste cancelar");
}