Dos primos luchan contra la tecnología

Aprendizaje y formación en informática profesional mediante videotutoriales

Evitando bloquear el GUI con SwingWorker

En ocasiones nuestros programas necesitan realizar operaciones de larga duración que llevan mucho tiempo como consultas a bases de datos o accesos de lectura/escritura a archivos grandes. Esto ocasiona que la GUI de nuestra aplicación no se refresque y se quede ‘congelada’ hasta que termina la operación de larga duración, lo que confunde al usuario que no sabe si debe esperar o si la aplicación se ha quedado ‘colgada’. Cualquier tarea que lleve más de medio segundo debería ser ejecutada en un hilo aparte del hilo de ejecución de swing.

Vamos a ver una pequeña introducción de la forma de gestionar los hilos de swing para hacernos una idea general de su funcionamiento.

Básicamente podemos decir que hay dos hilos de ejecución principales: el hilo que inicia la aplicación cuando creamos la GUI y el EDT conocido como Event Dispatching Thread que es el que nos interesa.
El EDT es el hilo de ejecución de las aplicaciones Swing. Este se encarga de dibujar y actualizar los componentes del GUI además de registrar los eventos generados por estos. Es una cola de tipo FIFO que procesa las tareas de una en una secuencialmente, lo que significa que hasta que una tarea no termina no puede empezar la siguiente.
Aquí es donde se encuentra el problema, ya que si ejecutamos las operaciones de larga duración dentro del hilo EDT provocamos que no se puedan repintar los componentes Swing asi como impedimos que pueda responder a eventos de teclado o ratón.

(more…)

Persistencia de objetos. Serialización.

La serialización consiste en codificar un objeto como una secuencia de bytes para almacenarlos en memoria o en un archivo para poder guardar el estado de los objetos aunque se cierre el programa. Es utilizada para conseguir persistencia entre diferentes sesiones y para poder transmitir objetos remotamente a través diferentes máquinas de una red, proceso conocido como invocación remota de objetos(RMI).

Para serializar un objeto, es necesario que el objeto mismo implemente el interfaz ‘Serializable’.

Al serializar un objeto, todos sus miembros son serializados aunque sean private. Para evitarlo debemos utilizar el modificador transient que ocultará estos miembros.

A continuación pongo un ejemplo de una colección de libros. Tenemos la clase ‘Libro’ que tiene 3 miembros con sus correspondientes setters y getters y que, por supuesto, implementa la interfaz Serializable.
También se puede encontrar la clase ‘Gestión’ con dos métodos, uno que serializa una lista de libros de ejemplo y otro método que recupera el objeto desde el archivo que contiene los objetos serializados. Lo que se ha hecho ha sido serializar la lista directamente.

(more…)

Ocultar ventana de CMD al ejecutar una aplicación en Windows (Java)

Tanto si creamos un .bat o un .exe para iniciar nuestra aplicación hecha en java tendremos una ventana del intérprete de comandos abierta de fondo.
En teoría este problema lo presenta el comando java mientras que el comando javaw no abre ninguna ventana de cmd. Pero en mi caso si que se queda la ventana abierta así que tuve que buscar solución.
Si no nos interesa la información que se pueda mostrar en esta ventana podemos hacer que se oculte nada más se inicie nuestra aplicación.
La orden a utilizar sería:

START /B javaw.exe -jar aplicacion.jar

El comando START inicia una ventana aparte para ejecutar un programa o comando y el parámetro  /B inicia la aplicación sin crear una ventana.

Leer el código fuente de una URL (Java)

En ocasiones necesitamos obtener el código fuente de una página web. Varios ejemplos de uso podrían ser:

  • Visualizar el código fuente en nuestra aplicación.
  • Seguir enlaces de una URL para comprobar que no hay enlaces rotos.
  • Guardar en disco todas las páginas de un website automáticamente.

Un breve código de ejemplo de una clase que recibe un String con la URL a leer y devuelve un String con el código fuente:  (more…)

Acceso a base de datos MySQL con JDBC (Java)

Para poder utilizar la base de datos MySQL desde una aplicación Java necesitamos descargar el conector para Java que ofrece MySQL en su sitio web
http://dev.mysql.com/downloads/connector/j/

Allí seleccionad la versión adecuada para vuestro servidor de base de datos.

Pongo una clase de ejemplo muy sencillo para ver cómo se realiza una consulta SQL común.

(more…)

Diálogo de selección de ficheros JFileChooser (Java)

Resulta muy frecuente que las aplicaciones necesiten trabajar con archivos para leer y guardar datos de manera que se pueda trabajar más adelante con ellos.

En esta ocasión vamos a ver el diálogo de selección de ficheros JFileChooser que permite seleccionar ficheros de nuestro disco duro o crear nuevos.


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;

public class MySelector {
  public static void main(String[] args) {
    MyFrame frame = new MyFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}

class MyFrame extends JFrame{
  private JButton botonOpen = new JButton("Abrir");
  private JButton botonSave = new JButton("Guardar");
  private MyFileListener myFileListener =
          new MyFileListener(this);
  public MyFrame(){
    super("Ejemplo de JFileChooser");
    Container container = getContentPane();
    container.setLayout(new BorderLayout());
    container.add(botonOpen, BorderLayout.WEST);
    container.add(botonSave, BorderLayout.EAST);
    botonOpen.addActionListener(myFileListener);
    botonSave.addActionListener(myFileListener);
  }
}

class MyFileListener implements ActionListener{
  private JFileChooser chooser = new JFileChooser();
  private JFrame frame;
  public MyFileListener(JFrame frame){
    this.frame = frame;
  }
  public void actionPerformed(ActionEvent ae) {
    String textButton = ae.getActionCommand();
    String dialogTitle = "Abrir un fichero";

    if (textButton.equals("Guardar"))
      dialogTitle = "Guardar un fichero";

    chooser.setDialogTitle(dialogTitle);
    chooser.setMultiSelectionEnabled(false);
    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

    int sel = chooser.showOpenDialog(frame);
    if (sel == JFileChooser.APPROVE_OPTION){
      File selectedFile = chooser.getSelectedFile();
      JOptionPane.showMessageDialog(
         frame,
         selectedFile.getAbsolutePath());
    }else{
      return;
    }
  }
}

Como métodos útiles de JFileChooser destacaremos:

  • setDialogTitle(): el título de la ventana.
  • setMultiSelectionEnabled(): permitir seleccionar varios ficheros al mismo tiempo.
  • setFileSelectionMode(): indica si se pueden seleccionar ficheros, directorios o ambos.
  • setFileFilter(): permite incluir filtros para el listado de archivos.

Arrastrar (drag) componentes con el ratón (Java)

En una ocasión tuve que hacer una aplicación para crear diagramas en la que tenía que insertar componentes swing como JButton o JLabel dentro de un frame y que permitía arrastrarlos (drag) con el ratón por medio de la interfaz MouseMotionListener por toda la superfice del contenedor.

Básicamente consiste en crear unos objetos derivados de JButton o de JLabel, por ejemplo, e implementarles un MouseMotionListener. Mediante el método mouseDragged se registra la variación de coordenadas del puntero del ratón cuando se arrastra el componente y se actualiza su posición.

Es importante recordar que el panel o frame que contenga esos elementos debe tener un layout nulo y que dichos elementos deben tener unas coordenadas iniciales establecidas por el método setBounds.

Aquí va un sencillo código de ejemplo:


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class DragTest {

public static void main(String[] args) {
  MyWindow window = new MyWindow();
    window.setVisible(true);
    window.setPreferredSize(new Dimension(400,400));
    window.pack();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}
class MyWindow extends JFrame{
  public MyWindow(){
    super("Drag test");
    Container container = getContentPane();
    container.setLayout(null);

MyButton boton1 = new MyButton("Move me");
    container.add(boton1);
    boton1.setBounds(10, 10, 100, 30);
  }
}
class MyButton extends JButton implements MouseMotionListener{
  public MyButton(String text){
    super.setText(text);
    addMouseMotionListener(this);
  }

public void mouseDragged(MouseEvent mme) {
    setLocation(
        this.getX() + mme.getX() - this.getWidth() / 2,
        this.getY() + mme.getY() - this.getHeight() / 2
    );
  }
  public void mouseMoved(MouseEvent mme) {}
}