May 14

chuidiang-editores

 

Acabo de subir a google-code los fuentes de otro pequeño proyecto que me traigo entre manos, chuidiang-editores.

De momento son simplemente unas clases que heredan de JFormattedTextField y hace de editores simples: un EditorNumerico, EditorDate, EditorLongitud, EditorLatitud, etc. Por supuesto, intentando que sólo admitan números correctos, que se puedan poner restricciones, como que el número esté entre un mínimo y un máximo, etc.

También hay un EditorPanelGeneral. Es un JPanel al que se añaden editores de una forma simple y él se encarga del Layout y de colocarlos de forma automática. Este JPanel admite como dato un Hashtable. Con las claves identifica a qué editor pertenece el dato y se lo pasa. En el método getDato() devuelve un Hashtable con los datos de cada uno de los editores.

Y eso es más o menos lo que hay. La intención final es ligar todo esto con base de datos, de forma que para un conjunto de columnas dadas de unas tablas, se construya automáticamente el formulario y más adelante, facilitar también el tema de consultas e inserciones, así como la presentación en un JTable de los resultados, con sus botones de crear/editar/borrar, filtro, etc.

Ahí van algunos enlaces:

y sólo falta lo de siempre, porque empezar he empezado con ganas. Lo que hay que ver es lo que dura.

May 06

Clase Desktop en Java 6

 

Gracias a este tema del foro de java, he descubierto la clase Desktop de Java 6. Esta clase permite abrir e imprimir ficheros con la aplicación por defecto que indique el sistema operativo. También permite lanzar el navegador por defecto con una URI determinada o el cliente de correo.

Un código tan tonto como este

Desktop.getDesktop().open(new File("c:/pingucd/readme.txt"));

en windows abrirá el notepad con el fichero readme.txt.

Interesante y simplifica bastante algunas cosas.

Feb 28

Programando el mando de wii con java

Un compañero de trabajo se ha encontrado una librería java motej que permite conectarse con el mando de la wii y extraer información de sus sensores, como el de posición o el de infrarrojos, etc. Una vez que conseguimos extraer en nuestro código la información detectada con el mando, podemos hacer lo que queramos con ella y el único límite es nuestra imaginación. Como ejemplos, puedes ver los videos de esta página Johnny Chung Lee, Esos proyectos posiblemente no están hechos con esta librería, sino en Visual C#. Los ejemplos son:

  • Con unas pegatinas reflectantes en nuestros dedos, podemos moverlos y dibujar unos puntos en la pantalla del ordenador que se muevan de acuerdo con nuestros dedos.
  • Podemos proyectar la pantalla del ordenador en alguna pared o en la mesa. Luego, con unos lápices adecuadamente preparados, podemos controlar el ordenador sobre esa proyección, como si fuera una pantalla táctil.
  • Finalmente, el más asombroso de todos, el tercer video. Colocándonos el sensor en la visera de una gorra, el ordenador puede saber desde dónde estamos mirando la pantalla, haciendo girar una imagen 3D en ella de acuerdo a nuestra posición. El efecto 3D según se ve en el video es realmente alucinante. Lo pongo aquí

En fin, como dice mi compañero, hay que comprarse un bluetooth (para conectar el mando con el ordenador) y un mando de la wii y buscarse un sitio tranquilo para empezar a jugar.

Feb 18

Gráficos en google code

Yo sigo dándole vueltas a mi librería gráfica. Después de haber creado mi proyecto en http://proyectos.chuidiang.com/graficos/ y mi repositorio maven en http://maven2.chuidiang.com/, estuve pensando que me quedaba un poco cutre el tema de bajarse los fuentes, ya que están metidos en un .jar creado y subido por maven. Así que he dado de alta el proyecto en google.code, así los fuentes están disponibles a través de subversion.

El proyecto está en http://code.google.com/p/chuidiang-graficos/ y he creado dos proyectos dentro del mismo repositorio de subversión. Uno llamado GRAFICOS que es la librería en sí misma. El otro GRAFICOS-EJEMPLOS para los programas de prueba de la librería.

Los fuentes se pueden bajar anónimamente por medio del siguiente comando

svn checkout http://chuidiang-graficos.googlecode.com/svn/GRAFICOS/PRINCIPAL/ chuidiang-graficos-read-only

Además, te dan espacio para una wiki y para bugs. A ver si tengo algo de tiempo para jugar con ello y darle un pequeño empujón.

Y ya puestos, igual intento darla de alta también en sourceforge, así juego más.

Jan 25

… y del ruso pasamos al Excel con POI

Siguiendo el post anterior, ya me  he dado la pequeña paliza de ir externalizando String por todo el código eclipse para sacar los textos y que alguien los traduzca al inglés y al ruso. Yo domino varios idiomas: colombiano, cubano, chileno, argentino, mexicano, etc, pero inglés no y el ruso menos, así que todo el trabajo para el traductor, que para eso le pagan.

Me comentan que el traductor, cómo no, es ofimático, así que lo de darle los ficheros de propiedades que encima son textos técnicos pues no vale. Tenemos que pasar esos textos en una columna de una hoja excel. Debemos añadir otra columna en la hoja con explicaciones de los textos más complejos, palabras que no se traducen o significado de ciertas palabras técnicas o propias del proyecto. Y dos columnas más vacías, una para que lo ponga en inglés y otra en ruso.

Pues bien, es una oportunidad estupenda para aprender a usar POI y hacer un programa java que haga:

  • Se le indica un directorio a partir del cual buscar, que será el directorio del proyecto. A partir de ahí, busca recursivamente todos los ficheros messages.properties generados por eclipse. Para la búsqueda de ficheros recursivamente, he usado un pequeño buscador de ficheros en java que me hice en su día.
  • Lee cada uno de esos ficheros y genera varios EXCEL con el formato indicado anteriormente. De cosecha propia he añadido una columna con la "clave" de la etiqueta en el properties, de forma que luego pueda generar los messages_en.properties y messages_ru.properties también de forma automática. Me he inventado lo de _ru, de ruso.
  • Salva el excel poniendo un nombre al fichero xls que corresponda más o menos con el paquete donde está el messages.properties. Algo como cambiar los puntos de los paquetes por _

Dicho y hecho. Me he cogido POI, un pequeño ejemplo de uso de otro compañero y me he hecho el programita java. Ahora ando con la tontería de poner en la hoja una cabecera bonita, unos bordes para las celdas y demás.

Aprovecho para dar unas pequeñas indicaciones de cómo se usa POI para crear un EXCEL.

Ante todo, bajarnos el jar de poi. Como lo he hecho con maven, lo he añadido como dependencia en el pom.xml copiando del pom.xml de poi, así que sin problemas, maven crea el proyecto eclipse y se baja el jar.

Y en el código java, lo primero, crear el cuaderno de excel y una hoja

HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet("Hoja 1");

creamos ahora una fila, la fila cero, y le ponemos celdas de cabecera

HSSFRow row = sheet1.createRow((short) 0);
HSSFCell cell = row.createCell((short) 0);  // celda de columna 0
cell.setCellValue("ESPAÑOL");
cell = row.createCell((short) 1);  // celda de columna 1
cell.setCellValue("RUSO");

y así sucesivamente con el resto de filas y columnas y todos los datos. Finalmente, para guardar definitivamente el fichero

FileOutputStream fileOut = new FileOutputStream("fichero.xls");
wb.write(fileOut);
fileOut.close();

y listo. La verdad es que me ha asombrado lo sencillo que es. Ahora ando metiendo estilos en las celdas y tampoco parece complejo, aunque sí un poco más laborioso. Así que ya tengo dos entretenimientos que hacer. Un par de pequeños tutoriales en la Chuwiki: Un ejemplo sencillo y algo como "ExportTableModelToExcel" y el viceinverso.

Jan 24

Traduciendo al ruso

Nuestros proyectos son -o eran- habitualmente para España, por lo que nunca hemos prestado demasiada atención al idioma de las interfaces gráficas, ni a la internacionalización de java, ni a los ResourceBundle, ni a ninguna otra cosa parecida. El texto va directamente en el código y en español.

Pero la hemos liado. Tenemos que hacer uno de nuestros proyectos para un país de habla rusa. Tenemos que traducir todas las etiquetas al ruso, con caracteres cirílicos, por supuesto.

Pues nada, me he puesto a ello. He cogido eclipse y con su "externalize strings…" me he puesto a sacar ficheros de propiedades con los textos. Eclipse es una pequeña maravilla y todo eso se hacer rápido. Sin embargo, se me han planteado varias dudas.

Hay cosas, como los formatos de fecha y hora que no sé si tienen o no tienen traducción al ruso, si el formato usado en código para las máscaras sería correcto o no en ruso. Por ejemplo, en inglés suele ponerse delante el mes, luego el día y finalmente el año, mientras que en español va primero el día. Algo como dd/mm/yy en inglés podría ser mm/dd/yy. Encima, esa posible traducción visible no sé hasta qué punto es compatible con el cirílico.

Por otro lado tenemos mensajes que se componen de cosas como "hay " + variable + "chirimbolos en " +otraVariable. ¿Se compondrá la frase igual en ruso?. El que nos traduzca los ficheros de propiedades traducirá literalmente "hay" y "chirimbolos en". La cadena en cirílico se compondrá de la misma forma. ¿tendrá sentido?. Veo aquí que la internacionalización no es sólo sacar cadenas de texto y usar ResourceBundle. Posiblemente también hubieras sido necesario usar cosas como la clase MessageFormat, que compone mensajes de ese tipo. Siempre me pregunté para qué serviría esa clase. Ahora lo veo más claro. El formato del mensaje sería "hay {0} chirimbolos en {1}". Indicándole al traductor que [0} {1} son números y no se traducen, el traductor puede componer la frase correctamente en ruso sabiendo todo el significado.

Y se me ocurren otras chorradas, pero supongo que Windows es Windows para todos. ¿localhost es también localhost en ruso o hay que ponerlo en cirílico? ¿y los nombres de los servidores con los que debemos conectarnos por socket? ¿En cirílico se usan las mismas comas, puntos, barras separadoras de directorios \ y demás con el mismo significado?.

En fin, que veo altas probabilidades de pequeños problemas de funcionamiento de código debidos a la traducción a cirílico de ciertas cosas…. Si ya en español tenemos problemas con las vocales acentuadas que a veces salen como gurruños o cuadraditos según cómo se escriban y vengan de la base de datos, no te digo si encima no hay dos letras que se parezcan.

Jan 18

Ordenar y Filtrar JTable en Java

La versión 6 de java soporta, por fin, el ordenado y filtrado de tablas JTable. Existen clases que se pueden asociar al JTable, de forma que las filas de este podrán ordenarse pinchando en la cabecera de la columna, o bien podrán filtrarse para ocultar algunas de ellas pasando un filtro desde código.

Los trozos de código que pongo aquí son copia de los de la API.

Para que una tabla se pueda ordenar pinchando en la cabecera, el trozo de código es el siguiente

TableModel modelo = …;
JTable tabla = new JTable(modelo);
tabla.setRowSorter (new TableRowSorter(modelo));

Naturalmente, podemos hacer nuestro propio RowSorter para que las filas se ordenen como nosotros queramos.

Una vez ordenada la tabla de alguna forma, tenemos un problema con el número de fila. Si el número de fila es, por ejemplo, el 7, ese 7 ¿correspone a la fila 7 del modelo o a la fila 7 que se ve en la tabla?. Para solucionar esto, el JTable proporciona además métodos para convertir el número de fila del modelo a número de fila de la vista y vicevesa

int indiceModelo = tabla.convertRowIndexToModel (indiceTablaOrdenada);
int indiceTablaOrdenada = tabla.convertRowIndexToView (indiceModelo);

En cuanto a filtrado, podemos pasar al JTable un filtro, de forma que sólo se mostrarán aquellas filas que pasen el filtro. Disponemos, por supuesto, de varios filtros por defecto y podemos, por supuesto, hacernos nuestros propios filtros. El código para pasar un filtro que muestre todas aquellas filas que contengan "foo" en alguna de sus columnas puede ser este

TableRowSorter sorter = new TableRowSorter(modelo);
sorter.setRowFilter (RowFilter.regexFilter(".*foo.*"));
tabla.setRowSorter (sorter);

Me alegra que por fin hayan incluido esto. Por fin podremos tirar a la basura unas tablas que nos hicimos justo con estas dos posibilidades y que, por supuesto, se nos embarullaron más de lo debido según iba tocando y añadiendo cosas la gente.

 

Dec 21

Constructores vs Setters

Lo que cuento aquí está extraido del artículo de Martin Fowler de Inversión de Control, pero como es interesante, pues eso, lo cuento aquí.

La cuestión, a la hora de inicializar una clase, es si lo hacemos pasándole todo lo necesario a través del constructor o bien por medio de métodos set().

En principio, es mucho más claro usar los constructores. En un constructor está claro qué debemos pasar a esa clase para que funcione correctamente y desde el mismo momento que la instanciamos, esa clase está en condiciones de funcionar, ya que  tiene todo lo necesario. Con los método set() no tenemos esa facilidad. Puede haber métodos set() que no sean necesarios para el correcto funcionamiento de la clase, por lo que no tendríamos necesidad de llamarlos. Y al revés, un método set() obligado se nos puede olvidar y la clase no funcionaría. Además, si no conocemos la clase, no podemos saber con los métodos set() cuales son obligatorio y cuales no, mientras que en el constructor está claro.

Por todo ello, en principio es mejor usar constructores. Pero hay una pega.

A veces hay muchas configuraciones posibles para la clase, según qué parámetros pasemos. Eso obligaría a hacer varios constructores. Si además, usamos herencia, es posible que en nuestra clase, además de nuestros constructores, tengamos que redefinir los de la clase padre, por lo que el número de constructores puede llegar a ser abrumador. Incluso a veces, al llamar al constructor de la clase padre, es posible que no podamos construir sobre la marcha uno de sus parámetros.

En ese caso, posiblemente sea mejor usar los métodos set(). Y como propone Martin Fowler, quizás sea buena idea llamar initParametro() a los que son obligatorios o a los que sólo se puede llamar una vez, aunque rompamos la regla de los beans de java.

Por mi parte, siempre había tenido esta duda y me había tropezado con los dos problemas -no saber que métodos set() son obligatorios o tener que hacer varios miles de constructores-. Todo esto me ha parecido buena idea, -usar constructores si es posible o métodos init() para los obligatorios- así que trataré de aplicarla a partir de ahora.

Dec 19

iBATIS

Al final creo que me he decidido por iBATIS. No he hecho más que unas pruebas sencillas con varios -Hibernate, iBATIS, JPOX, etc-, pero al final iBATIS me ha parecido el más "controlable".

Hibernate me ha fallado con la ingeniería inversa, no es capaz de tragarse el mismo los ficheros de configuración que él ha generado, aparte que los plugins y herramientas adicionales parecen bastante descuidadas.

JPOX ni siquiera he conseguido hacerlo funcionar -el plugin para eclipse, ni siquiera lo he probado a mano-. De todas formas, parece que toca los bytecodes después de compilar el código y eso me da "mal rollo".

iBATIS no me ha dado ninguna pega. El plugin para eclipse ha funcionado a la primera y el código generado funciona a la primera. Además, me gusta el tener los SQL visibles en un fichero, ya que siempre da la sensación de tener más control sobre lo que se está haciendo.

Un compañero mio probó cayenne, y aunque la ingeniería inversa se hace estupendamente con una interface gráfica de usuario, en los java beans mete cosas propias de él y no me convenció.

Por supuesto, y siguiendo mi costumbre, he puesto mis pruebas sobre iBATIS en la Chuwiki. Estoy deseando que me toque codificar algo contra una BD…

Dec 13

StringBuilder

Desde java 1.5 tenemos la clase StringBuilder. Esta clase es similar a StringBuffer, pero con la diferencia de que no es segura para su uso con varios hilos. Esto, si sólo usamos un hilo, la hace más eficiente que el uso de StringBuffer, ya que no tiene los métodos sincronizados.

La clase StringBuilder es ideal para esos String que construimos a base de concatenar trozos localmente dentro de un método, por ejemplo, para sacar una salida por pantalla o construir una sentencia SQL.

Hay sin embargo un curioso detalle más. El compilador de java es listo y si concatenamos cadenas con el típico +, como por ejemplo

String unaCadena = "hola, " + tuNombre + ". ¿Cómo estas?";

el compilador reemplaza todo esto por una construcción en condiciones usando StringBuilder. En tiempo de ejecución ese código es igual de eficiente que si usáramos StringBuilder y más eficiente que si usamos StringBuffer, contrariamente a lo que pasaba en las primeras versiones de java.

Ahora me alegro de no haberme acostumbrado nunca al uso de StringBuffer.

Tienes todo esto mucho más detallado en Manipulación de cadenas en java.