Jun 16

El lado oscuro de Java

En un post del foro de java y gracias a chusterboy he descubierto que java tiene un lado oscuro.

Resulta que aunque no está en la API oficial de java, con el JRE y JDK de Sun vienen ciertas clases que están disponibles y se pueden usar. Me refiero en concreto a las de com.sun.image.codec.jpeg, que permiten el manejo de imágenes jpg. En la API advierten que otras implementaciones del JDK o JRE que no sean las de SUN pueden no tenerlas, pero el caso es que están y no sé qué porcentaje de JREs que hay por hay NO son las de SUN.

Supongo que es cuestión ahora de abrir los .jar que vienen con el JRE o JDK de sun y buscar más "java oscuro"

Actualización: Como bien comentan en los comentarios, conviene no usar estas clases del lado oscuro, ya que en siguientes versiones de java pueden no estar y no todas las implementaciones de JDK las tienen. Además, hay muchas implementaciones de JDK que no son java, en concreto las de MacOS.

Jun 09

Copy - Paste desde java

En java, con Toolkit.getDefaultToolkit.getSystemClipboard() podemos acceder al portapapeles del sistema. Con los métodos ahí disponibles podemos introducir contenido o extraer el contenido que otras aplicaciones han dejado allí.

Para contenido que no sea de texto, tendremos que "currarnoslo" un poco, pero para contenido de texto es muy sencillo, simplemente porque los componentes de texto de java swing ya tienen implementados los controles de copy-cup-paste con los típicos Ctrl-C, Ctrl-X y Ctrl-V, así que no tenemos ni siquiera que acceder al portapapeles ni hacer absolutamente nada de código.

Si lo que queremos son las típicas opciones en un menú o en unos botones con la funcionalidad copy-cut-paste, también es sencillo para texto normal. La clase DefaultEditorKit ya tiene implementadas estas acciones como Action, así que bastará con pedírselas o instanciarlas y ponerlas en los JMenuItem o JButton.

Action accionCopiar = new DefaultEditorKit.CopyAction();
Action accionPegar = new DefaultEditorKit.PasteAction();
Aciont accionCortar = new DefaultEditorKit.CutAction();

como hemos dicho, estas Action se pueden poner directamente en los JButton o JMenuItem. Funcionarán sobre el componente de texto que tenga el foco en el momento de pulsarlos.

Más detalles en copy/cut/paste para componentes de texto.

May 20

MessageFormat en Java

 

Java nos proporciona la clase MessageFormat para la construcción de mensajes de texto que se muestran en pantalla. En vez de construir un mensaje concatenando cadenas (para los puristas: no pongo StringBuilder para simplificar)

String mensaje = "se han encontrado " + numeroErrores + "errores";

deberíamos usar la clase MessageFormat, de esta manera

String mensaje = MessageFormat.format ("se han encontrado {0} errores", numeroErrores);

En este caso, MessageFormat reemplaza {0} por el valor de la variable que le pasamos. Podemos poner más variables poniendo {1}, {2}  y así sucesivamente.

¿Por qué es importante usar MessageFormat en vez de construir la cadena como en el primer ejemplo?

Aparte de que MessageFormat tiene más posibilidades que no menciono aquí, un motivo importante es la posible traducción a otros idiomas de nuestra aplicación. Antes de nada, que quede claro que no tengo ni papa de inglés, así que el ejemplo que pongo seguro que es totalmente incorrecto. Quédate con la idea y no con los detalles.

Supongamos que usamos la primera forma, construyendo el String a partir de varios cachos. Si para preparar el código para otro idioma usamos la internacionalización de nuestro IDE, lo más probable es que nos saque un fichero de propiedades con algo como esto

propiedad1=se han encontrado
propiedad2=errores

Ahora vamos y le damos esto a nuestro traductor favorito. El ve un trozo de frase y una palabra. De ninguna forma puede adivinar que forman parte de la misma frase, así que traduce cada cacho separado y nos lo da

propiedad1=have been found
propiedad2=errors

y la frase en nuestro código quedará como "have been found 3 errors". Ya digo que no sé inglés, pero posiblemente esta frase no está bien construida para un inglés.

Sin embargo, si hubiesemos usado MessageFormat, habríamos obtenido este fichero de propiedades

propiedad1=se han encontrado {0} errores

y advirtiendo al traductor que los {0} serán datos que se pongan en esa posición de la frase, él posiblemente lo traduzca por algo como

propiedad1={0} errors have been found

y el texto quedará "3 errors have been found". Insisto en que no sé inglés, pero posiblemente esta frase esté mejor construida que la anterior.

 

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.

May 01

Python con MySQL

 

Hay una tontería de la conexión de python con MySQL que me ha llamado la atención y aprovecho para comentar aquí. El tema es que según obtengamos el cursor de la conexión para hacer las consultas, podemos acceder a los resultados de una manera o de otra.

Si obtenemos el cursor de esta manera

conn = MySQLdb.connect (….)
cursor = conn.cursor()

una vez que hagamos una consulta y obtengamos una de las filas resultado, debemos acceder a cada uno de los campos usando un índice de un array

cursor.execute ("select * from tabla")
fila = cursor.fetchone()
# para acceder al primer campo
print fila[0]  

Sin embargo, al obtener el cursor podemos decir que queremos que las filas sean dictionaries, en vez de tuplas, de manera que podemos acceder a los campos usando el nombre del campo, en vez de un índice. Para ello, basta con obtener el cursor de esta manera

conn = MySQLdb.connect (…)
cursor = conn.cursor(MySQLdb.cursors.DictCursor)

y así podemos acceder a los campos a través de su nombre

cursor.execute("select * from tabla")
fila = cursor.fecthone()
# para acceder a uno de los campos
print fila["nombre_columna"]

Una tontería, pero estoy acostumbrado a java y a C++ y no a lenguajes tan flexibles.

 

Apr 25

sitemap para SMF

Hace tiempo comenté en un post que el foro SMF es un desastre para que lo indexe google y, de hecho, no aparecía en google ninguno de los temas de mi foro de java. Intenté instalar el plugin seo4smf para tratar de arreglarlo, pero no conseguí que me funcionara. Al final, como comenté en aquel post, me hice un pequeño programa java que generara un fichero sitemap.xml para colgarlo en el foro.

Esa opción no era buena del todo. Conseguí que google indexara los temas del foro, pero tenía que actualizar el sitemap periódicamente a mano. Así que decidí hacerme un pequeño script sitemap.php que hiciera de sitemap para google de forma automática.

Este script, al llamarlo, consulta en la base de datos el campo id_topic de la tabla smf_topics. Es la única información que necesita para generar el fichero XML de sitemap. El script dice que devuelve un "Content-Type : application/xml" para que cuando google lo consulte piense que es un fichero XML, luego envía los tags XML correspondientes al sitemap.

Adjunto el código php por si a alguien le interesa

<?php
header(’Content-Type: application/xml’);
include (’Settings.php’);

print (’<?xml version="1.0" encoding="UTF-8"?>’);
print (’<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">’);

$link = mysql_connect ($db_server, $db_user, $db_passwd) or die ("<center>No se puede conectar con la base de datos\n</center>\n");
$query=’select id_topic from smf_topics’;
$result=mysql_db_query ($db_name, $query, $link);

while ($row = mysql_fetch_array ($result))
{
   print (’<url>’);
   print (’<loc>’);
   print (’http://foro.chuidiang.com/index.php?topic=’.$row[0]);
   print (’</loc>’);
   print (’</url>’);
}
mysql_free_result($result);
print (’</urlset>’);
?>

El include "Settings.php" únicamente incluye un fichero de configuración del foro, en el que están las variables con el nombre de la base de datos $db_name, el usuario $db_user y la password $db_passwd. Ojo, no le busqueis pegas, que las tiene. Yo no tengo ni idea de PHP.

 

Apr 23

Python: Una de cal y una de arena

Sé que "una de cal y una de arena" significa una cosa buena y una cosa mala. El problema es que nunca he sabido si la cal es la mala, la arena la buena o a la viceinversa.

Hace tiempo comenté que iba a hacer una pequeña aplicación web en python para pedirle a la gente que metiera cada mes el tiempo que dedica a cada uno de los proyectos, de forma que luego sacara en excel una tabla con dichos tiempos. Pues bien, ya está hecha (un poco de aquella manera) y funcionando. Así que tras esta mínima experiencia con python, ahí van un par de impresiones, una buena y otra mala, una de cal y otra de arena.

La cosa mala: Me da la impresión, al igual que casi todos los lenguajes de script en los que defines las cosas sobre la marcha, que python es un lenguaje muy difícil de mantener. Al no definirse claramente los tipos, cuando en una función o método recibes parámetros, no tienes ni idea de lo que recibes, salvo que lo pongas muy bien comentado. De hecho, en eclipse con el plugin pydev para programar en python, el autocompletar que te muestra los nombres de atributos y métodos de las clases, eclipse sólo te puede mostrar aquellos atributos y clases que hayas usado previamente en el código.

En java, por ejemplo, hay que declararlo todo, por lo que en cualquier momento sabes cada variable de qué tipo es y qué cosas tiene o a las que puedes llamar. No dependes (salvo para entenderlo mejor) de que el programador se haya acordado de comentar adecuadamente el código.

La cosa buena: Precisamente esta falta de tipado y el poder meter una manzana donde se espera un higo me da la impresión que hace de python un lenguaje muy flexible, y pongo un ejemplo. Puesto que mi aplicación es web, en casi todos los métodos/funciones que he hecho recibo de parámetro un Request Object, que el mismo servidor web se encarga de pasarme y con el que tengo acceso a los parámetros de la petición http, con el que puedo escribir los tag html que se verán en el navegador, etc. Pues bien, para mis pruebas sin servidor web desde eclipse, me hice una clase MiClase con un método write() similar al de Request Object, lo instancié y llamé a mis métodos a pelo pasándoles una instancia de MiClase. El código "tragó" con eso perfectamente, y la salida html salía por donde decía MiClase, es decir, por pantalla normal.

En otros lenguajes como java habría sido necesario heredar del objeto en cuestión y sobreescribir los métodos necesarios, quizás incluso declarar un constructor obligatorio con los parámetros raros que tuviera la clase padre. En java es aconsejable el uso de interfaces precisamente por este motivo, para poder cambiar una cosa por otra sin "cargar" con la clase original heredando de ella. En python no hacen falta interfaces. Basta con que la clase sustituta tenga los métodos que se usen de la clase original.

Todo esto me hace preguntarme si lo del desarrollo rápido de lenguajes como python se refiere a que no es necesario declarar los tipos (desde luego, eso ahorra tiempo, pero me parece un tiempo mínimo respecto a todo el proceso o el tiempo que puedes perder en depuración mientras decides si una variable es de un tipo u otro), o bien se debe a esta flexibilidad del lenguaje, que permite mezclar churras con merinas y todo funciona como debe.

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.