viernes, 17 de junio de 2016

Truco Java - Añadir imágenes a un JTable desde un campo Blob en MySQL

Hoy hemos realizado una encuesta a través del twitter del blog preguntandoos sobre que lenguaje queríais el siguiente truco y ha ganado JAVA.

Por suerte estoy realizando un master de JAVA ahora mismo y a diario me surgen problemas y dudas que voy solventando y que, seguramente, sean las mismas que tengáis vosotros si estáis empezando con este lenguaje.

En el truco que nos ocupa hoy os voy a enseñar cómo solucioné la cuestión de mostrar un campo de imagen (tipo BLOB en MySQL) en un JTable.


Os pondré el código que rellena la tabla y luego os destacaré un par de secciones que son las que considero más importantes.

Este es el código en cuestión:

    /**
     * Procedimiento LlenarTabla
     * Utilizando el procedimiento modeloImagen.listImagen,
     * se rellena la tabla pasada por parametro.
     * @param tablaImagenes
     * @throws java.sql.SQLException
     * @throws java.io.IOException
     */
    public void LlenarTabla(JTable tablaImagenes) throws SQLException, IOException{
        DefaultTableModel modeloTabla = new DefaultTableModel() {
            @Override //Redefinimos el método getColumnClass
            public Class getColumnClass(int column){
                switch(column) {
                    case 0: return Object.class;
                    case 1: return Object.class;
                    case 2: return Object.class;
                    case 3: return ImageIcon.class;
                    default: return Object.class;
                }
            }
        };
        //Establecemos el modelo correspondiente en la JTable
        tablaImagenes.setModel(modeloTabla);
        
        //Añadimos las columnas correspondientes
        modeloTabla.addColumn("ID IMAGEN");
        modeloTabla.addColumn("ES CATEGORIA");
        modeloTabla.addColumn("DESCRIPCION");
        modeloTabla.addColumn("IMAGEN"); //Esta es la columna [3], es la que
                                         //nos interesa que sea una imagen.
                
        Object[] columna = new Object[4];
        
        ArrayList<imagen> listaImagenes = modeloImagenes.ListarImagenXEsCategoria("","");
        
        int numRegistros = listaImagenes.size();
        
        for (int i = 0; i < numRegistros; i++) {
            columna[0] = listaImagenes.get(i).getIdImagen();
            columna[1] = listaImagenes.get(i).getEsCategoria();
            columna[2] = listaImagenes.get(i).getDescripcion(); 

            //Transformamos el campo blob en ImageIcon
            Blob blob = listaImagenes.get(i).getImagen();
            int blobLength = (int) blob.length();  
            byte[] bytes = blob.getBytes(1, blobLength);
            blob.free();
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
            ImageIcon icon = new ImageIcon(img); 
            
            //Añadimos la imagen a la columna correspondiente
            columna[3] = icon;
            
            //Añadimos la fila al modelo
            modeloTabla.addRow(columna);
            
            //Establecemos el alto de la fila                                   
            tablaImagenes.setRowHeight(i, icon.getIconHeight());    
        }
        
   } 



No voy a entrar en el detalle de cómo recupero los datos de MySQL ni de cómo se define la clase Imagen (si queréis el código podéis pedírmelo en los comentarios y os lo facilitaré), pero sí quiero que prestéis atención a este código:

         DefaultTableModel modeloTabla = new DefaultTableModel() {
            @Override //Redefinimos el método getColumnClass
            public Class getColumnClass(int column){
                switch(column) {
                    case 0: return Object.class;
                    case 1: return Object.class;
                    case 2: return Object.class;
                    case 3: return ImageIcon.class;
                    default: return Object.class;
                }
            }
        };


Ese fragmento de código define el modelo que utilizará el objeto JTable y sobre el hemos de redefinir el método getColumnClass para que, en la columna [3] nos devuelva un ImageIcon, que es lo que queremos mostrar.

Otra parte importante del código, y que seguro que muchos ya conocéis, es el encargado de convertir el campo BLOB en un ImageIcon.
  
            //Transformamos el campo blob en ImageIcon
            Blob blob = listaImagenes.get(i).getImagen();
            int blobLength = (int) blob.length();  
            byte[] bytes = blob.getBytes(1, blobLength);
            blob.free();
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
            ImageIcon icon = new ImageIcon(img); 
            

Con estos sencillos pasos podemos obtener el resultado deseado.

Resultado final en una aplicación SWING

Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

jueves, 16 de junio de 2016

Truco Delphi - Alternar colores de filas en DBGrid

Hoy os presento un pequeño truco que hará que vuestros DBGrids luzcan mucho mejor añadiendo unas pocas lineas de código.

Lo que tratamos de conseguir es que nuestro DBGrid presente las filas con colores alternos y además que la fila seleccionada se resalte también de manera alterna.


Para conseguir este objetivo debemos escribir la función GridDrawColumnCell como sigue:


procedure TfrmPrincipal.GridDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  RowColors: array[Boolean] of TColor = (clSilver, clWhite);
  RowSelectedColors: array[Boolean] of TColor = (clHotLight, clHighlight);
var
  OddRow: Boolean;
begin
  if (Sender is TDBGrid) then
  begin
    OddRow := Odd(TDBGrid(Sender).DataSource.DataSet.RecNo);
    if (gdSelected in State) then
      TDBGrid(Sender).Canvas.Brush.Color := RowSelectedColors[OddRow]
    else
      TDBGrid(Sender).Canvas.Brush.Color := RowColors[OddRow];
    TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;


Este procedimiento lo podemos poner en el formulario donde esté el DBGrid o bien en una unidad aparte y luego importarla con el comando Uses. Si incluimos el procedimiento en el formulario, es importante hacerlo como procedimiento de clase:

 TfrmPrincipal = class(TForm)

    { Otros métodos y propiedades del formulario }

    procedure GridDrawColumnCell(Sender: TObject; const Rect: TRect;
                                 DataCol: Integer; Column: TColumn; State: TGridDrawState);
  private
    { Private declarations }

  public
    { Public declarations }
  end;



De esta manera podremos seleccionar el DBGrid y asignar el procedimiento al evento OnDrawColumnCell.


Si tienes cualquier duda o comentario recuerda que puedes exponerlo aquí o bien mediante nuestro twitter y facebook.
Compartir:

miércoles, 15 de junio de 2016

Truco Delphi - Prevenir la ejecución de más de una instancia de nuestra aplicación (I)


Hace ya bastante tiempo que no posteo, pero eso no quiere decir que me haya olvidado de vosotros.
Como no dispongo de mucho tiempo para continuar con el curso de Lazarus y postear de forma asidua los artículos que tenía previstos, voy a empezar a postear pequeños tips y códigos de ejemplo para resolver pequeños problemas que me surgen en el día a día.

Hoy quiero mostraros como hacer que vuestra aplicación no se ejecute más de una vez, pero, en lugar de manteniendo la instancia más antigua, haciendo que la nueva instancia tome el control, es decir, que la nueva ejecución sustituya a la antigua.

Para ello nos vamos a basar en el procedimiento de WinApi GetCurrentProcessId, que nos dará el id de proceso del programa que estamos ejecutando y en el objeto TApplication para obtener el ExeName que será el que buscaremos.



Básicamente lo que pretendemos es terminar cualquier proceso que se llame como el nuestro, pero que no sea el nuestro :D


Añadimos el siguiente código en el evento OnCreate de nuestro formulario principal.

procedure TfrmPrincipal.FormCreate(Sender: TObject);
begin
  FProcessID := GetCurrentProcessId;
  FExeName   := ExtractFileName(Application.ExeName);
  
  CerrarInstancias;
end;

Este es el código que recorrerá todos los procesos de Windows y eliminará las instancias que existan de nuestra aplicación excepto la actual.

procedure TfrmPrincipal.CerrarInstancias;
const
  PROCESS_TERMINATE = $0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);


  while Integer(ContinueLoop) <> 0 do
  begin

      if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
          UpperCase(FExeName)) or
          (UpperCase(FProcessEntry32.szExeFile) =
          UpperCase(FExeName)))  and
         (FProcessEntry32.th32ProcessID <> FProcessID)
      then
      begin
        TerminateProcess(OpenProcess(PROCESS_TERMINATE,
                                    BOOL(0),
                                    FProcessEntry32.th32ProcessID),
                                    0);
      end;

       ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);

end;

Mas adelante pondré otras maneras de prevenir la ejecución de más de una instancia de nuestras aplicaciones.
Compartir:

jueves, 31 de marzo de 2016

Hola Mundo multilingüe

¡Hola Mundo!

Aprovechando que he implementado SyntaxHighLighter en el blog, vamos a hacer un repaso por la mayoría de lenguajes de programación haciendo lo primero que debería hacer todo programador que empieza con un nuevo lenguaje de programación; el programa "Hola Mundo"

Espero que os guste el formato. A partir de ahora empezaré a incluir entradas con tips de programación en diferentes lenguaje y rutinas interesantes para que las tengamos todos a mano.

ColdFusion

<html>
<head>
<title>Test</title>
</head>
<body>

  <cfset message = "¡Hola Mundo!">
  <cfoutput>#message#</cfoutput>

</body>
</html>

C#

using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("¡Hola Mundo!");           
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

C++

#include <iostream>
 
int main()
{
  std::cout << "¡Hola Mundo!" << std::endl;
  return 0;
}

Delphi/Pascal

program Hello;
begin
  writeln ('¡Hola Mundo!');
  readln
end.

JavaScript

<!DOCTYPE HTML>
<html>
<body>

  <p>Header...</p>

  <script>
    alert('¡Hola Mundo!')
  </script>

  <p>...Footer</p>

</body>
</html>

Java
public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("¡Hola Mundo!");
    }

}

Perl

  #!/usr/bin/env perl

  use v5.10.0;
  use warnings;
  use strict;

  say "¡Hola Mundo!";

Php

<html>
<head>
<title>Test</title>
</head>
<body>

 <?php
  $message = "¡Hola Mundo!";
  echo $message;
 ?>

</body>
</html>

PowerShell

$strString = "¡Hola Mundo!"
write-host $strString

Python

print("¡Hola Mundo!")

Ruby

puts '¡Hola Mundo!'

Visual Basic

Module Hello
  Sub Main()
      MsgBox("¡Hola Mundo!")  
  End Sub
End Module

Compartir:

lunes, 28 de marzo de 2016

Juegos para programar: Lightbot: Code Hour

Hace ya varias semanas desde la última entrada y varias más desde el primer artículo sobre "Juegos para programar". Lo cierto es que he estado bastante ocupado con el Master de Java, Semana Santa, Vacaciones, etc... pero aquí estamos de nuevo para volver a bloguear más a menudo.


LightBot: Code Hour

Hoy os traemos un juego que hará las delicias de los pequeños y no tan pequeños. Se llama LightBot: Code Hour. Este pequeño juego es gratuito y nos ofrece una secuencia de puzzles que irán creciendo en dificultad y que nos acercarán a temas tan propios de la programación como los procedimientos y los bucles.


¿En que consiste?

El juego consiste en dirigir nuestro LightBot hacia una serie de cuadrículas azules, distribuidas por un tablero, y encendiendo una bombilla sobre ellos. La gracia del asunto es que tenemos un número máximo de acciones que podemos llevar a cabo para acabar cada una de las fases.



Tendréis la posibilidad de seleccionar el idioma que queráis (entre ellos el español) y el género de vuestro LightBot.

El juego puede resultar algo corto, pero si tenemos en cuenta que es gratuito y a quién va dirigido, no me cabe duda de que será muy interesante para los más pequeños.



Otras versiones

Si os quedáis con ganas de más, tenéis disponibles dos versiones adicionales de LightBot, una de 4 a 8 años y otra para edades de 9 en adelante. Desafortunadamente estas versiones ya son de pago y su precio oscila entre los 2,99€ y los 3,18€ dependiendo de la versión y la plataforma.

Además tenéis una versión de navegador a la que podéis acceder desde aquí y jugar gratuitamente


Espero que os haya gustado este post y que me dejéis en los comentarios si queréis que hable sobre algún juego concreto que consideréis interesante para esta temática y lo incluiré sin problemas.

Compartir:

miércoles, 2 de marzo de 2016

Retrospectiva. Febrero 2016



Ya estamos en Marzo y, de la misma manera que el mes pasado y como haremos todos los meses, toca hacer una retrospectiva sobre el mes que acaba de pasar.

A veces las cosas no salen como uno quiere, unas veces debido a imprevistos y otras (la mayoría) por errores de estimación o planificación. Este mes en el blog hemos tenido un poco de todo: Por un lado, como algunos ya sabéis, estoy viviendo en Mallorca, pero mi familia está en Almería. Esto implica que, aproximadamente, cada dos semana estoy yendo a ver a mi mujer y a mis hijas, y este mes no había tenido en cuenta estos viajes para la planificación del blog. En realidad esto no supone ningún problema ya que he decidido tomarme este blog como lo que es, mi hobbie, así que no pienso agobiarme por no publicar un post durante la semana ni nada por el estilo. Por otro lado muchos que me seguís en las redes sociales sabréis que he empezado un curso experto de Java, (J2SE, J2EE y Android) y el tiempo que me va a consumir su realización.

En la retrospectiva de Enero os comentaba que intentaría subir a 9 los post durante este Febrero; esto no ha podido ser así debido a lo que os comentaba un poco más arriba. También quería seguir añadiendo mejoras al blog que han tenido que posponerse para este mes. Lo que si ha podido empezar es el curso de Delphi sobre Lazarus cuyos dos primeros capítulos tenéis aquí:


Esta misma semana tendréis el siguiente capítulo disponible. Si no queréis perderos nada os recomiendo que os suscribáis al canal de youtube así como al feed de este blog, pero eso ya es cosa vuestra (aunque os lo agradecería enormemente).

Para este mes de Marzo voy a ser bastante conservador en cuanto objetivos. Voy a plantearme hacer entre 7-9 entradas de las cuales 4 serán capítulos del curso de Delphi, de manera que me quede tiempo suficiente para continuar mi curso de Delphi. Incluiré las mejoras que tenía pensadas para Febrero y añadiré una página destinada a los cursos y otra destinada a una recopilación de blogs que suelo leer y que me parecen interesantes.

Sin más, me despido hasta el próximo post.


Code Safe…
Compartir:

domingo, 28 de febrero de 2016

Juegos para programar: Bit by Bit

Siempre he dicho que la programación es un ejercicio mental, independiente del lenguaje utilizado. Programar es el medio para resolver problemas utilizando un lenguaje de programación apropiado, por eso en la carrera de ingeniería informática se enseñan matemáticas, lógica, algorítmia, etc.

Creo que es de vital importancia, si sois padres, que enseñéis a vuestros hijos/as a pensar por si mismos, a sacar conclusiones, deducir, planificar y ejecutar. Hay muchas maneras de hacerlo: juegos de estrategia como el ajedrez o juegos de construcción tipo Lego, Tente, Megablocks, son un buen ejemplo. Estos juegos ayudan a los más pequeños a desarrollar su inteligencia visio-espacial y deductiva.

Hoy en día con la tecnología disponible, son muchas las opciones que tenemos al alcance de la mano. Con esta serie de entradas semanales pretendo acercaros los juegos y aplicaciones, tanto para Android como para PC/navegador que considero interesantes para el desarrollo de los más pequeños. Recordad que siempre es recomendable estar con ellos mientras usan cualquier dispositivo conectado a internet, de forma que vosotros los controléis en todo momento y de esa manera, además, compartáis un buen rato jugando, aunque sea con una "maquinita".


Bit by Bit: Programming game:


El juego que os quiero presentar hoy es Bit by Bit: Programming game. Podréis encontrarlo en Play Store y la mecánica es tan simple que os sorprenderá. Se trata de una serie de puzzles predefinidos que tenemos que ir resolviendo para poder pasar de nivel. Para la resolución de estos puzzles tendremos que utilizar distintos objetos (serán diferentes para cada nivel) para llevar a los Bits de diferentes colores a su correspondiente destino. 



Parece fácil ¿no?. De hecho lo es. Aunque se irá complicando con el paso de los niveles, la curva es bastante aceptable, y niños a partir de 5-6 años no encontrarán demasiados problemas en resolver los primeros niveles una vez hayan aprendido la mecánica.


¿Por que es interesante este juego?


Este juego ha sido desarrollado con ayuda de niños, padres y especialistas en educación y, mientras juegan, los más peques aprenderán cosas como:
  • Planificación
  • Creatividad en la resolución de problemas
  • Pensamiento analítico y lógico
Os recomiendo que lo probéis, os va a gustar. Solamente tiene una pega que comprobaréis después de la primera partida, la publicidad. Después de cada nivel el juego nos mostrará un vídeo publicitario bastante molesto. La manera de evitar esto es activando el modo avión y dejando nuestro dispositivo completamente offline

Me sorprende las pocas descargas que tiene este juego y creo que es debido a una mala campaña de marqueting. Imagino que con el tiempo añadirán mas niveles y pondrán la opción de comprarlo para no tener esa molesta publicidad, siempre y cuando tengan descargas suficientes.



Si conocéis juegos de estas características y queréis compartirlos, podéis dejarme vuestros comentarios debajo del post o directamente mencionándome en mi cuenta de twitter y los tendré en cuenta para futuros posts.
Compartir:
Con la tecnología de Blogger.

BoosterBlog

BoosterBlog
BoosterBlog

Timeline Twitter

Seguidores

Seguidores