Ir al contenido principal

Almacenar imágenes en MySQL con JFileChooser



Almacenar imágenes en MySQL con JFileChooser

Para almacenar imágenes en una base de datos existen varias formas, desde almacenar la imagen directamente en la BD en un cambo BLOOB o almacenar solo el nombre de la imagen, además de copiarla a una carpeta donde se almacenen todas las imágenes.
En este ejemplo se utilizara un JFileChooser para elegir la imagen a guardar, para posteriormente cuando el usuario guarde el registro la aplicación copiara la imagen a una carpeta predeterminada llamada imágenes y en la base de datos solo almacenara el nombre de la imagen para su posterior visualización.


1.- Para este ejemplo se crea un nuevo proyecto llamado imagenesBD, y posteriormente se crean dos packages uno llamado clases donde se almacena el programa escrito en java y otro package llamado images donde se copiaran las imágenes que el usuario almacene en la BD.
Además se agrega la librería MySQL JDBC Driver para la conexión con MySQL.
La estructura del proyecto queda como en la siguiente imagen.



2.- Para este ejemplo se crea la base de datos imagenes, donde se crear la tabla productos, que permite almacenar el nombre de un producto y su imagen, teniendo como llave principal el idProducto, adicionalmente se insertan a la tabla un par de registros, téngase en cuenta que las imágenes también se deben de copiar a la carpeta images, que fue creado anteriormente.

CREATE DATABASE IF NOT EXISTS `imagenes` DEFAULT CHARACTER SET latin1 COLLATE latin1_spanish_ci;
USE `imagenes`;

--
-- Estructura de tabla para la tabla `productos`
--

CREATE TABLE IF NOT EXISTS `productos` (
  `idProducto` int(11) NOT NULL AUTO_INCREMENT,
  `nombre` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  `imagen` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`idProducto`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci AUTO_INCREMENT=1;

--
-- Volcado de datos para la tabla `productos`
--

INSERT INTO `productos` (`idProducto`, `nombre`, `imagen`) VALUES
(1, 'sol', 'sol.png'),
(2, 'luna', 'luna.png');


3.- El siguiente paso es diseñar una interfaz gráfica como la siguiente, donde se tienen controles básicos para desplazarse por los registros de la base de datos, además de contener la opción para nuevo donde se habilitara un botón para navegar por los directorios y así poder seleccionar la imagen deseada, para este ejemplo se filtraran las imágenes para mostrar solo .png y .jpg las imágenes se visualizaran en un JLabel.



4.- En el panel de Navegación de componentes se hace clic con el botón derecho en Other Components, posteriormente en Add From Palette + Swing Windows + File Chooser, de esta forma se insertar el JFileChooser al proyecto y permitirá mostrar y utilizar el cuadro de dialogo Abrir.


5.- Una vez insertados los componentes quedara una estructura como la siguiente, donde ya se han renombrado cada uno de los componentes insertados.


6.- En la clase principal se insertan las siguientes librerías que permiten realizar la conexión con la BD, mostrar el cuadro de dialogo abrir y copiar archivos dentro de las carpetas.

//librería para el manejo de archivos
import java.io.File;
import java.io.IOException;

//librerías para copiar archivos
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

//librerías para conexión con la base de datos
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

//librería para almacenar temporalmente una imagen
import javax.swing.ImageIcon;

//librería para mostrar el cuadro de dialogo abrir
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

//librería para mostrar mensajes
import javax.swing.JOptionPane;

7.-  Dentro de la clase principal se declaran las siguientes variables miembros, que permiten realizar la conexión y almacenar la ruta y el nombre del archivo seleccionado.

private Connection co;
private ResultSet rs;
private Statement st;

private String nombreArchivo;
private String ruta;
private String nuevaRuta;
private File archivo;

8.- El método conectar realiza la conexión con la BD imágenes, y selecciona los productos dados de alta, además de seleccionar el primer registro y mostrarlo en los componentes correspondientes.

private void conectar() {
        try {
            co = DriverManager.getConnection("jdbc:mysql://localhost/imagenes", "root", "");
            st = co.createStatement();
            rs = st.executeQuery("Select * from productos");
            rs.next();
            llenarCampos();
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 0:" + err.getMessage());
        }
    }

9.- Este método muestra el primer registro.

public void primero() {
        try {
            rs.first();
            llenarCampos();
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 1:" + err.getMessage());
        }
    }

10.- Este método muestra el último registro.

public void ultimo() {
        try {
            rs.last();
            llenarCampos();
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 2:" + err.getMessage());
        }
    }

11.- Va recorriendo hacia atrás los registros.

    public void anterior() {
        try {
            if (!rs.isFirst()) {
                rs.previous();
                llenarCampos();
            }
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 3:" + err.getMessage());
        }
    }

12.- Va recorriendo hacia adelante los registros.

    public void siguiente() {
        try {
            if (!rs.isLast()) {
                rs.next();
                llenarCampos();
            }
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 4:" + err.getMessage());
        }
    }

13.- Inserta un nuevo registro y muestra el registro insertado.

    public void guardar() {
        try {
            String sql = "insert into productos(nombre,imagen) values ('" + this.jtfProducto.getText() + "','" + nombreArchivo + "');";
            st.executeUpdate(sql);
            JOptionPane.showMessageDialog(this, "Producto guardado");
            rs = st.executeQuery("Select * from productos");
            ultimo();
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 5:" + err.getMessage());
        }
    }

14.- Este método toma los datos almacenados en el RecordSet (rs) y los muestra en los JLabel y JTextField correspondientes.

   public void llenarCampos() {
        try {
            this.jlidProducto.setText(rs.getString("idProducto"));
            this.jtfProducto.setText(rs.getString("nombre"));
            this.jlNImagen.setText(rs.getString("imagen"));
            this.jlimagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/" + rs.getString("imagen"))));
        } catch (SQLException err) {
            JOptionPane.showMessageDialog(null, "Error 6:" + err.getMessage());
        } catch (NullPointerException err) {
            JOptionPane.showMessageDialog(null, "Error 7:" + err.getMessage());
        }
    }

15.- Con el siguiente método se protegen los datos, ya que al habilitar la opción de Nuevo, todos los botones para desplazarse se deshabilitan de tal modo que el usuario no pueda cambiar de registro accidentalmente.

public void bloquearDesbloquear(boolean todos) {
        this.jbAnterior.setEnabled(todos);
        this.jbSiguiente.setEnabled(todos);
        this.jbPrimero.setEnabled(todos);
        this.jbUltimo.setEnabled(todos);
        this.jbNuevo.setEnabled(todos);
        this.jbCargarImagen.setEnabled(!todos);
        this.jbGuardar.setEnabled(!todos);
    }

16.- En los eventos ActionPerformed de los botones de desplazamiento (jbPrimero, jbAnterior, jbSiguiente, jbUltimo) se manda llamar a los métodos correspondientes para el desplazamiento y visualización de los registros.

  private void jbPrimeroActionPerformed(java.awt.event.ActionEvent evt) {                                         
        this.primero();
    }                                         

    private void jbAnteriorActionPerformed(java.awt.event.ActionEvent evt) {                                          
        this.anterior();
    }                                         

    private void jbSiguienteActionPerformed(java.awt.event.ActionEvent evt) {                                           
        this.siguiente();
    }                                          

    private void jbUltimoActionPerformed(java.awt.event.ActionEvent evt) {                                         
        this.ultimo();
    }                  

17.-  Este método establece un filtro para que únicamente se muestren las imágenes con extensión PNG y JPG, al abrir el cuadro de dialogo Abrir, si el usuario presiona el botón Abrir el método almacena el nombre de la imagen, la ubicación actual, para posteriormente mostrar el jlImagen la imagen seleccionada.

public void cargarImagen(){
             try {
            ImageIcon imagen; //permite almacenar la imagen que se abre con el JFileChooser
            FileNameExtensionFilter filtro = new FileNameExtensionFilter("PNG,JPG", "png","jpg");
            jfcAbrirArchivo.setFileFilter(filtro);

            int abrir = jfcAbrirArchivo.showOpenDialog(this);

            if (abrir == JFileChooser.APPROVE_OPTION) {
                archivo = jfcAbrirArchivo.getSelectedFile();
                ruta = archivo.getAbsolutePath();
                nombreArchivo = archivo.getName();
                nuevaRuta = System.getProperty("user.dir") + "\\src\\images\\" + nombreArchivo;
               
                imagen = new ImageIcon(ruta);
               
                this.jlNImagen.setText(nombreArchivo);
                this.jlimagen.setIcon(imagen);
            }
        } catch (NullPointerException err) {
            JOptionPane.showMessageDialog(null, "Error 8:" + err.getMessage());
        }
    }

18.- El evento ActionPerformed del jbCargarImagen llama al método cargarImagen().

  private void jbCargarImagenActionPerformed(java.awt.event.ActionEvent evt) {                                              
        cargarImagen();
    }

19.- El evento ActionPerformed del jbNuevo borra el texto de jtfProdocto y jlNImagen, para que el usuario pueda dar nombre al nuevo producto, además bloquea los botones de desplazamiento y activa el botón para buscar la imagen y guardarla.

    private void jbNuevoActionPerformed(java.awt.event.ActionEvent evt) {                                       
        this.jtfProducto.setText("");
        this.jlNImagen.setText("");
        bloquearDesbloquear(false);
    } 

20.- El evento ActionPerformed del jbGuardar guarda el nuevo registro, además de copiar la imagen desde la ruta original a la carpeta images del proyecto, para tener todas las imágenes en el mismo lugar, y deshabilita los botones de búsqueda y guardar, y vuelve a habilitar los botones de navegación.

    private void jbGuardarActionPerformed(java.awt.event.ActionEvent evt) {                                          
        guardar();
        copiarArchivo(ruta, nuevaRuta);
        bloquearDesbloquear(true);
    }  

21.- Este método permite copiar cualquier archivo desde la ruta origen hasta la ruta destino.

    public static void copiarArchivo(String origen, String destino) {
        try {
            Path rutaOrigen = Paths.get(origen);
            Path rutaDestino = Paths.get(destino);
            CopyOption[] opciones = new CopyOption[]{
                StandardCopyOption.REPLACE_EXISTING,
                StandardCopyOption.COPY_ATTRIBUTES
            };
            Files.copy(rutaOrigen, rutaDestino, opciones);
        } catch (IOException err) {
            JOptionPane.showMessageDialog(null, "Error 9:" + err.getMessage());
        }
    }

22.- En la siguiente imagen se muestra el proyecto cuando se ejecuta, mostrando el nombre del producto y la imagen que esta almacenada en la carpeta images.



23.-  Al hacer clic en el botón nuevo se habilita la caja para escribir el nombre y el botón para abrir el cuadro de dialogo Abrir.



24.- Al hacer clic en el botón buscar (…) se muestra el cuadro de dialogo abrir, que permite navegar por las carpetas del sistema y seleccionar un archivo de extensión jpg o png.


Comentarios

Entradas más populares de este blog

Creación de Librerías en Java

Creación de Librerías en Java   Las librerías son un conjunto de clases con funciones especificas que ayudan a desarrollar aplicaciones más complejas de una forma sencilla, por ejemplo si se requiere realizar cálculos matemáticos y emplear el funciones como el Seno o Coseno, simplemente se importa la librería Math y se utilizan estos métodos, en lugar de desarrollarlos. Java cuenta con una extensa lista de librerías disponibles dentro del JDK o desarrolladas por terceros, pero también existe la posibilidad de desarrollar librerías propias para reutilizar de forma más eficiente el código, por ejemplo si se trabaja de forma cotidiana con conexión a base de datos, se pueden desarrollar métodos genéricos que realicen la conexión, que validen las consultas, etc. de forma que su uso reduzca el tiempo de desarrollo e incremente la productividad. Para este tutorial se van a crear dos proyectos en NetBeans, uno sera la librería y el otro proyecto hará uso de esta.

Elegir la clase a ejecutar en NetBeans, MVC

Elegir la clase a ejecutar en NetBeans Para que java pueda ejecutar una aplicación esta debe tener un método conocido como punto de entrada, este método tiene la sintaxis: void static void main(String [] sax){ //código } En ocasiones en una aplicación tiene varios puntos de entrada, que pueden servir para probar diferentes partes de la aplicación sin tener que recorrer o pasar por varias clases, para esto se puede seleccionar directamente en las propiedades del proyecto que clase será la principal.

Librerías JOptionPane para generar ventanas de entrada y salida de datos

Para poder introducir datos leídos desde el teclado existen varias formas, una de ellas hace uso de la librería javax.swing.JOptionPane que entre otras opciones permite mostrar ventanas para introducir datos, y ventanas para mostrar valores. Con el uso de esta librería se crean pequeñas interfaces definidas por el sistema, pero ya se hace uso de las librerías graficas swing, que se verán más adelante.