02 noviembre 2005

Poner imagen de fondo en una ventana

He estado haciendo unos experimentos para ver si consigo poner una imagen de fondo en una ventana. No sé si he llegado a la mejor solución, pero aquí hay una.

Lo primero es hacer una clase que herede de Container y redefina el método paint(Graphics g) de esta manera

class Contenedor extends Container
{
// La imagen que queremos de fondo, un fichero .gif
public ImageIcon icono = new ImageIcon ("./imagen.gif");

// Redefinición del método paint()
public void paint (Graphics g)
{
// Borramos todo y lo pintamos del color de fondo por defecto.
Rectangle r = g.getClipBounds();
g.setColor(this.getBackground());
g.fillRect (r.x, r.y, r.width, r.height);

// Pintamos la imagen
g.drawImage (icono.getImage(), 0,0,this);

// Hacemos que se pinten los botones dentro de este contenedor
super.paint(g);
}
}

Luego basta con instanciar un JFrame o JDialog y meterle este contenedor

JFrame ventana = new JFrame();
ventana.setContentPane(new Contenedor());

Con esto vale. Como pega es que la imagen no se repite si la ventana es más grande que la imagen. Esta sólo sale una vez.

Los componentes que se pinten en la ventana, (JButton y demás, salvo el JLabel), tienen su propio color de fondo y machacan la imagen. Si no se quiere así, habría que ir llamando a los método setOpaque(true) de los compoentes.

Unas variantes para esto pueden ser las siguientes:
  • En drawImage() podemos hacer que la imagen coja el tamaño del contenedor. Para ello hay que poner unos parámetros más e incluso el color de fondo: g.drawImage (icono.getImage(), 0, 0, this.getWidth(), this.getHeight(), this.getBackground(), this);
  • Si no damos tamaño a la imagen, pero sí ponemos el color de fondo, nos ahorramos borrar antes el contenedor. La pega es que si el contenedor es más grande que la imagen, todo ese sobrante no se borra.

Más sobre emule

Al final nada de nada. Por más pruebas que hago, el emule me deja colgado el ordenador.

Con las versiones antiguas (0.44d) no consigo nada, se sigue quedando colgado. También he probado con el emule plus sin resultado.

Mirando foros, he visto que determinados router y tarjetas de red dan problemas, generalmente de desconexión con internet, al usar emule. Hay gente que ha conseguido arreglar el problema actualizando drivers o con scripts que configuran las tarjetas de red de alguna forma especial. En mi caso, no he tenido suerte (aunque tampoco me lo he tomado muy en serio).

Mi conclusión final es que algunas tarjetas de red / routers no funcionan bien con emule. Como de momento no tengo intención de cambiar de tarjeta de red, paso de emule.

Al final he probado con kazaa. Me gusta menos la red de kazaa (hay menos cosas), pero al menos me funciona. kazaa mete mucha propaganda, pero he leido por ahi que hay una versión (kazaa lite) que es lo mismo, pero sin la propaganda ni spywares ni demás. Ya me la he bajado y algún día la probaré.

29 octubre 2005

Más de emule

Pues nada, lo del emule ni patrás.

Con la versión 0.44d se cuelga incluso antes que con la 0.46c
Al menos con esta última, si estoy trabajando o pongo música a la vez tarda más en colgarse (acaba haciéndolo).

En los foros también se mencionan problemas con la conexión, los moden, routers y demás. Yo sé que en ocasiones mi tarjeta de red (d-link airplus dwl 520+), mientras busca la red, deja el ordenador completamente colgado durante unos segundos, exactamente igual que hace el emule, pero con la diferencia de que el emule lo hace de forma permanente.

Me he bajado un driver nuevo para mi tarjeta, pero sigo con el mismo problema. Seguiré investigando y si es posible, trataré de pedir otra tarjeta prestada para ver si con el cambio de tarjeta no hay problema.

27 octubre 2005

Una de eMule

El otro día decidí probar todo el tema de eMule para ver qué tal va y que no me suene a chino.

Me bajé la versión 0.46c que parece que es la última.

El tema está bien, te puedes bajar montones de cosas. Lo que no me gusta demasiado es que no tienes control ninguno (o casi) de las descargas. Las cosas van bajando solas, cuando les apetece (o pueden), a la velocidad que pueden. Es normal que intentes bajar ficheros y no comiencen a descargar. En fin, es algo para tener encendido y corriendo en background mientras vamos trabajando.

Se me ha presentado un problema más grave. Cuando estoy trabajando con el ordenador, no pasa nada, pero si lo dejo sólo con el eMule puesto, el ordenador se cuelga. No funciona el ratón ni el teclado ni nada de nada. Hay que apagar el ordenador a lo bestia.

Mirando por los foros de internet, he visto que el problema es relativamente habitual (junto con desconexiones completas de internet). También en esos foros he visto que el problema se presenta a partir de la versión 0.45a y posteriores.

Aunque las anteriores presentan algunos problemas de seguridad (según los foros), supongo que es mejor pasarse a una más antigua y no tener que resetear el ordenador cada cuarto de hora.

26 octubre 2005

Captura de teclas en un JTextField de java

Para limitar el tipo de caracteres o la entrada en un JTexField, tenemos muchas posibles soluciones.

En http://members.lycos.co.uk/chuidiang/ejemplos/JTextField/limita_caracteres.html hay una en la que se usa un Document.

Otra solución de más bajo nivel consiste en capturar las teclas según se pulsan y decidir si se aceptan o no para escribir en el JTextField. Por ejemplo, podemos capturar la tecla y escribirla en el JTextField sólo si es un número y rechazarla si es una letra.

Para ello, tenemos que añadir un KeyListener a nuestro JTextField. Cada vez que se pulse una tecla, se avisará al método keyTyped(KeyEvent e) de nuestro KeyListener. Del KeyEvent que nos pasan como parámetro podemos obtener qué tecla se ha pulsado (qué caracter) y rechazarla o no según nos convenga.

Por ejemplo, para aceptar sólo números, el código sería este:

JTextField textField = new JTextField(10);
textField.addKeyListener(new KeyAdapter()
{
public void keyTyped(KeyEvent e)
{
char caracter = e.getKeyChar();
if(((caracter < '0') ||
(caracter > '9')) &&
(caracter != KeyEvent.VK_BACK_SPACE))
{
e.consume();
}
}
});

Además de comprobar si caracter no está entre 0 y 9, comprobamos también que se admita la tecla VK_BACK_SPACE, porque si no, no podremos borrar lo que escribamos.

El método e.consume() hace que esa pulsación de tecla se rechace y el JTextField no la trate. El resultado es que cualquier cosa que no sea una cifra o el backspace se rechaza. Si queremos meter decimales, deberíamos aceptar también el punto decimal.

Este método tiene sin embargo una pega respecto al Document. Si en otro lugar copiamos un cacho de texto y lo pegamos sobre nuestro JTextField, eso no es equivalente a pulsar las teclas del texto copiado de una en una, sino que simplemente habremos pulsado Ctrl-V (en windows). Este control el JTextField lo trata directamente y pega el texto dentro del JTextField, sin ningún tipo de comprobación de si es o no un número.

Por este motivo, salvo que queramos algún "efecto especial" como hacer "beep" cada vez que se pulse una tecla que no se debe, es mejor usar el Document, o bien, debemos hacer un tratamiento algo más complejo de las teclas a pulsar.

25 octubre 2005

Uso de strtok()

strtok() es una función de C que permite partir una cadena en subcadenas usando como separador los caracteres que queramos.

Supongamos que tenemos una cadena con una frase y queremos separarla en palabras. Como separador de palabras usaremos los espacios, comas, dos puntos, punto y comas y puntos.

Lo primero es hacer una copia de nuestra cadena original, puesto que la función strtok() la estropea (va reemplazando separadores por caracteres \0). Para la copia podemos usar strdup(), que creo que es propia de C en unix o bien strcpy() que sí es standard.

Para obtener el primer token (la primera palabra), hay que llamar a strtok() pasando como parámetros la cadena que queremos analizar (la copia) y una cadena con los caracteres separadores

char *primeraPalabra = strtok(cadena, " .,;:");

Si primeraPalabra es NULL, no hay palabras en la cadena. A partir de aqui, para que nos devuelva los siguientes tokens (palabras) hay que llamar a la misma función, pero pasando NULL como primer parámetro. La función recuerda la cadena y la última palabra que devolvió y continua con la siguiente.

Lo mejor es meter todo en un bucle

char *token = primeraPalabra;
while (token != NULL)
{
token = strtok (NULL; " .,;:");
// token es ahora la siguiente palabra o NULL. Aqui debemos guardarla en algún sitio,
// escribirla en pantalla o lo que queramos.
}

Precisamente por recordar strtok() su estado en sucesivas llamadas, no es una función segura para usar con hilos. Lo que hace un hilo con ella puede estropear lo que hace el otro. Tampoco podemos dentro de un mismo hilo ir analizando dos cadenas distintas en paralelo. Habría que analizar completamente una y luego la otra.

23 octubre 2005

El patrón composite

Aprovechando el tema de las interfaces y su ejemplo, el de sacar la salida por impresora, pantalla o base de datos, voy a contar un poco en qué consiste el patrón de diseño compuesto (o "composite").

Supongamos que el gracioso que mencionabamos en las interfaces, nos pide poder sacar en la pantalla y en la impresora a la vez. Una solución es hacerse una clase PantallaEImpresora que implemente Escritor y escriba en pantalla y en impresora.

Sin embargo, hay una solución mejor. Hacer la clase PantallaEImpresora tiene la pega tonta de que necesitamos repetir el código de nuestra clase Pantalla y de nuestra clase Impresora. En nuestro tonto ejemplo, el código es tonto y no se pierde mucho tiempo en repetirlo, pero en un programa serio, seguramente no se hace tan rápido. Además, ¿por qué reptetir el código que ya tenemos hecho, en contra de la filosofía de reutilización?.

Una solución mejor es hacerse una clase "compuesto". Esta clase guarda dentro una lista de Escritores y a su vez implementa la interface Escritor. En el método escribe(), lo que hace es ir llamando a los métodos escribe() de todos los Escritor que tiene guardados. Por supuesto, puede tener métodos para añadir o borrar Escritores sobre la marcha.

El código puede ser parecido a este

class CompuestoEscritores implements Escritor
{

// Lista de escritores
private LinkedList escritores = new LinkedList();

// Añade un escritor a la lista
public void addEscritor (Escritor escritor)
{
escritores.add(escritor);
}

// LLama al escribe() de todos los escritores
public void escribe (String cadena)
{
for (int i=0;i<escritores.size();i++)
{
((Escritor)escritores.get(i)).escribe(cadena);
}
}
}

Con esta clase tan tonta, podemos permitir que nuestro código anterior sea capaz de sacar los resultados en varios sitios a la vez, eligiendo qué sitios. Además, si inventamos un nuevo sitios (por ejemplo, enviar los resultados por red) bastará como antes hacer la clase Escritor correspondiente y podemos añadirla tanto aquí como a nuestro método de cálculos.

Una pequeña tontería, el código de CompuestoEscritores lo acabo de poner sobre la marcha, igual ni siquiera compila....

22 octubre 2005

Por qué usar interfaces

Una pequeña explicación de por qué usar interfaces al programar. Aunque los ejemplos son java, la idea vale para cualquier lenguaje orientado a objetos.

Imaginemos que hacemos un programa que echa unas cuentas y va presentando en pantalla unos resultados. Puede ser algo como esto

void metodoConLasCuentas()
{
double valor=this.cuentas(datos);
System.out.println ("El valor es "+valor);
double valor2 = this.otrasCuentas(datos);
System.out.println ("El otro valor es " + valor2);
}

Ya está el programa. Se lo enseñamos a nuestro jefe, a nuestro cliente, a nuestro mejor amigo o al gracioso de turno y nos dice ... "Me gustaría poder sacar eso por impresora".

Nos ponemos manos a la obra y cambiamos nuestro programa

void metodoConLasCuentas()
{
double valor=this.cuentas(datos);
this.sacaPorImpresora ("El valor es "+valor);
double valor2 = this.otrasCuentas(datos);
this.sacaPorImpresora ("El otro valor es " + valor2);
}

Volvemos a enseñárselo al graciosillo y nos dice ... "Es que yo querría poder elegir sobre la marcha si lo quiero en pantalla o en impresora".

Nuevamente nos ponemos a tocar el código, pero esta vez algo más complejo

void metodoConLasCuentas()
{
double valor=this.cuentas(datos);

if (porImprsora==true)
this.sacaPorImpresora ("El valor es "+valor);
else
System.out.println ("El valor es "+valor);

double valor2 = this.otrasCuentas(datos);

if (porImpresora==true)
this.sacaPorImpresora ("El otro valor es " + valor2);
else
System.out.println ("El otro valor es " + valor2);
}

Nuevamente el gracios de ideas infinitas nos dice ... "Maravilloso, pero sería bueno poder guardar esos valores en base de datos".

Hartos de tocar el código decidimos implementar una solución que nos valga para todas las peticiones estúpidas del graciosillo. La solución es usar una interface. Hacemos nuestra interface así

interface Escritor
{
public void escribe (String cadena);
}

Ahora hacemos varias clases que implementen la interface, una clase Pantalla con el System.out.println, una clase Impresora con el sacaPorImpresora y una clase ABaseDeDatos con algo que sea capaz de meter esa cadena en la base de datos.

Nuestro código queda así de bonito ahora

void metodoConLasCuentas (Escritor escritor)
{
double valor=this.cuentas(datos);
escritor.escribe ("El valor es "+valor);
double valor2 = this.otrasCuentas(datos);
escritor.escribe ("El otro valor es " + valor2);
}

Llamando a nuestro método pasándole una clase Pantalla, sacará el texto por pantalla, con una clase Impresora, lo sacará por impresora y con un ABaseDeDatos lo guardará en base de datos.

Ya no tenemos que tocar nunca más nuestro código. Únicamente hacernos una nueva clase para la nueva idea del graciosillo y llamar a nuestro método con la nueva clase.

Este es un ejemplo tonto, pero si nos fijamos en java, hay multitud de sitios donde se usa.
  • Un JButton admite una interface ActionListener con un método actionPerformed(). El botón está hecho una única vez para siempre, y pasándole una Interface ActionListener, ese botón hace lo que queramos nosotros. Esta vez la gente de java eran los programadores y nosotros los graciosillos que queremos que el botón haga no sé qué.
  • Un JTable admite una interface TableModel. El TableModel es la interface y somos nosotros los que debemos rellenar los métodos. De esta forma un JTable hecho una sola vez es capaz de pintar cualquier tabla de datos, sin necesidad de tocarla por dentro. Únicamente tenemos que hacernos nuestra clase TableModel y pasársela al JTable.
  • Un Thread admite una interface Runnable. Esta clase Thread es capaz de hacer que se ejecute en un hilo aparte cualquier cosa que nosotros queramos. Únicamente hay que implementar el método run() de la interface Runnable y pasarle eso a la clase Thread.
  • etc, etc, etc.

Un buscador de rpm

En http://rpmfind.net/ hay un buscador de rmp (paquetes para instalar en determinadas distribuciones de linux).

Simplemente escribimos el nombre del programa que queremos instalar y nos indica los rpm para descargar.

19 octubre 2005

La clase java.awt.Robot

La clase java.awt.Robot permite hacer todo lo que puede hacer un usuario. Esta clase simula pulsaciones de teclas, movimientos de ratón y clicks del mismo.

Hay dos posibles utilidades que se me ocurren, aunque seguro que hay más.

La primera es para hacer demos o ayudas. Podemos presentar una aplicación y hacer que el ratón se vaya moviendo de un sitio a otro, haciendo cliks y así ver cómo funciona la aplicación.

La otra posibilidad, quizás más interesante, es para las pruebas unitarias de una interface gráfica.

Cuando se hace código orientado a objetos con clases y demás, se pueden hacer lo que se llaman pruebas unitarias. Estas pruebas consisten en hacer un main() para cada clase y hacer código que pruebe esa clase, para saber si está bien o mal. Por ejemplo, si tengo mi clase Matematicas con un metodo suma (int a, int b) que me devuelve la suma de a y b, la prueba unitaria consistiría en hacer un main que instancie la clase Matematicas y que llame al metodo suma() con varios valores, comprobando que el resultado que devuelve es correcto.

Un requisito habitual de estas pruebas unitarias es que el que va a probar no tenga que hacer nada. Simplemente arrancar la prueba y esta debe darle un OK o un FALLO. Esto es fácil de hacer con determinadas clases, pero casi imposible cuando la clase es una ventana. Si al apretar el botón "ayuda" debe salir una ventana con la ayuda, es muy dificil sólo con código apretar el botón de "ayuda" y ver si sale la ventana.

Aquí es dónde entra la clase java.awt.Robot. Como puede simular el movimiento de ratón y el click, es posible con ella hacer que se pulse el botón "ayuda". En cuanto a ver si la ventana de ayuda es visible, bastaría con preguntarle ventana.isShowing(). Con la clase java.awt.Robot podemos llevar el ratón a un JTextField, hacer click en él para que gane el foco, simular la pulsación de teclas para escribir algo en él, mover el ratón a un botón "Aceptar" y pulsarlo, es decir, la secuencia típica de entrada de datos en un formulario.

plugin de vi para eclipse

Llevo muchos años usando el vi y para mi es uno de los editores más potentes y que permite hacer las cosas más rápidamente. Cuesta al principio, pero cuando se conoce le da mil vueltas a cualquier editor de windows.

La única ventaja que veo a los editores de los entornos de desarrollo como eclipse o netbeans, es la posibilidad de autocompletar los nombres de métodos y clase al programar, ver la ayuda sobre la marcha, los parámetros que hay que poner en los métodos, etc, etc. Sin embargo, a la hora de reorganizar el código, mover lineas de un lado a otro, cambiarlas, buscar, etc, etc, echo mucho de menos el vi. De hecho, en estos editores me encuentro "atado" y con falta de opciones, usar el ratón para hacer cosas como seleccionar me parece lento, ...

Por ello, me he decidido a buscar un plugin de eclipse para ver si se el editor se puede comportar como el vi.

Primero encontré viPlugin, pero es de pago. Se instala, funciona bien, pero cada poco sale un popup indicando que la versión es de prueba y que debemos pagar unos 15 euros.

Rebuscando más, vi que existe una versión más antigua de viPlugin en sourceforge, gratuita. La instalé y tiene una pequeña pega. Cuando abro un fichero el viPlugin funciona fatal. Da igual como mueva el cursor, que va dando saltos por la pantalla y acaba llegando al final de fichero sin posibilidad de moverse. Lo más curioso es que si formateo el código (con jalopy o con la opción de formateo de código de eclipse) entonces ya sí funciona bien. De todas formas, cerrando y volviendo a abrir el código ya formateado, vuelve a ir mal. Es necesario darle a formatear otra vez.

Todo esto me hace pensar que puede haber algún problema con los retornos de carro (trabajo en windows y el vi es por excelencia de unix, donde los caracteres de fin de línea son distintos) o con algún otro tema del fuente, como tipo de caracter (ascii, us-ascii, utf-80, etc).

En fin, intentaré ver si encuentro el error o seguiré buscando más plugins.

18 octubre 2005

Sobre Debian

En http://www.mononeurona.org/index.php?secmenu=23 hay una página con un montón de tutoriales bsatante interesantes y muy claros sobre cosas de debian/linux.

Habla sobre todo de instalaciones y configuraciones de cosas sobre linux, como apache, mysql, php, informix, correo, etc.

17 octubre 2005

Me han fastidiado los de oracle

En el trabajo tenemos y tratamos de mejorar un conjunto de clases java para facilitar los programas que manejan base de datos. Básicamente la idea que tenemos es la siguiente:

Para cada posible tipo de campo de la base de datos tenemos un editor, es decir tenemos varios editores capaces de manejar los datos que nos devuelve un resultSet.getObject(): String, BigDecimal, Double, etc, etc. Todos esos editores implementan una interface común de tomaDatos() y dameDatos(). Estos editores se pueden configurar con las restricciones de los campos en la base de datos (número de cifras, de decimales, es obligatorio, es editable, etc) que se pueden leer automáticamente con los metadatos desde java.

Tenemos una clase que lee un fichero de configuración. Ese fichero contiene los nombres de las tablas de base de datos y el tipo de editor que debemos usar para ese campo, con sus restricciones. Ese fichero se genera automáticamente con un programita java que nos hemos hecho y que consulta los metadatos de la base de datos. Hemos optado por este fichero de configuración por no tener que ir leyendo en tiempo de ejecución los metadatos de la base de datos.

Tenemos también un panel al que se le pasan nombres de campos de la base de datos. El panel consulta el fichero de configuracion (que también se le pasa), instancia el editor adecuado para ese campo, lo configura con sus restricciones y lo coloca en el panel. Con esta clase creamos todos los formularios de forma casi automática.

El panel tienen dos metodos tomaDatos() y dameDatos() que reciben y dan un Hashtable. La clave del Hashtable es el nombre del campo de la base de datos y el valor es el valor que nos devuelve el ResultSet. De esta forma, rellenando el formulario y llamando al dameDatos(), obtenemos un Hashtable con todos los campos del formulario rellenos. El tomaDatos() lo que hace es repartir los valores del Hashtable a los editores individuales que hay dentro del panel.

Por supuesto, tenemos un TableModel que en cada fila admite uno de estos Hashtables y un JTable al que dándole los nombres de los campos que queremos que se vean, añade las columnas correspondientes.

Finalmente, tenemos una clase a la que dándole un String con un select de oracle, es capaz de realizar la consulta y construirnos los Hashtables correspondientes. Esta clase, si le damos cualquier sentencia SQL con nombres de campos entre # y un Hashtable, reemplaza los nombres de campos entre # por los valores del Hashtable. De esta forma se construyen los insert, delete, update e incluso los where de los select de forma más o menos automática. Por ejemplo, si hacemos "select * from tabla where campo=#campo#" y le pasamos un Hashtable con una clave "campo" y con valor Integer=3, esta clase reemplaza el #campo# por un 3. El select quedaría asi "select * from tabla where campo=3".

Con todo esto, para hacer un programa que trabaje con base de datos, creamos un fichero de configuración con nuestro programa independiente. Escribimos los select, insert,update en un fichero de configuracion. Los leemos y lo pasamos a nuestra clase de consultas, que nos devuelve directamente Hashtables. Estos los podemos meter tal cual en una tabla o en un formulario que se construyen solos con un par de líneas de código. De la misma forma, leyendo datos nuevos de un formulario y reemplazando campos entre # en el insert correspondiente, podemos insertar.

¿Cual es el problema?. Para construir el Hashtable con el resultset que obtenemos del select de SQL, necesitamos leer los metadatos del ResultSet. Estos metadatos sólo nos devuelven el nombre del campo, pero no de la tabla ni del esquema al que pertenece dicho campo ( ver última línea en http://www.oracle.com/technology/sample_code/tech/java/codesnippet/jdbc/OracleResultSetMetaData.html). Esto nos plantea el problema que si el select pide dos campos con el mismo nombre en distintas tablas, a través de los metadatos del ResultSet no podemos distinguir qué columna es qué campo. No queda más remedio que hacer los select con cosas como "select tabla1.nombre as nombre_1, tabla2.nombre as nombre_2 ...", que no deja de ser un incordio, puesto que hay que acordarse de hacerlo y no es algo que nos haga el código automáticamente.

_gxx_personality_v0

En varias ocasiones me han llegado correos de gente que quieren correr algunos de los ejemplos de mi página web y tienen problemas. El problema suele un error del estilo

undefined reference to '_gxx_personality_v0'

El problema no es del ejemplo. No sé muy bien a qué se debe, pero da la impresión de que en algunas versiones de linux han hecho depender el compilador de C (el gcc) de alguna librería propia del de C++ (el g++).

Buscando por internet (_gxx_personality_v0 en google) he visto que hay montones de entradas en los foros referenciando este error.

Las soluciones que se proponen parecen ser:
  • Usar g++ en vez de gcc al compilar, aunque sea un programa de C en vez de C++
  • Añadir a mano el linkado con la libreria /usr/lib/libstdc++.so. Bastaría con añadir una opción -lstdc++ en la línea de compilado con gcc.
Con esto, en teoría estaría resuelto el problema. Parece, de todas formas, que en versiones más modernas de linux se ha corregido el error.

En http://mapserver.gis.umn.edu/data2/wilma/mapserver-users/0303/msg00377.html hay un mensaje de un foro en el que básicamente explica estas dos soluciones.



16 octubre 2005

DVD2DivX V4

En DVD2DivX V4 hay una página interesante en la que cuenta, además de poder descargar todo lo necesario, cómo pasar una película DVD a formato DivX.

Grabando con la AverTV 203

Por fin me he puesto a grabar algo un poco más en serio con la AverTV 203.

Me gusta más que la Pinnacle PC TV Pro. Esta me daba algún problema cuando la señal no era buena. Dejaba de grabar sin más. Además, no permitía grabar en cualquier formato, simplemente grababa en mpeg-1 y ya está (la opción de mpeg-II es de pago aparte).

La Aver TV me da también algún problema, pero es secundario. Mientras está grabando, se me ha quedado colgada la imagen. Sin embargo, sigue grabando y la grabación luego está bien. También alguna vez en el arranque da un error. Hay que matar la aplicación y volverla a arrancar. Lo mejor de todo es que es capaz de grabar con cualquier codec que tengamos instalado, por lo que es posible grabar directamente en divX o cualquier otro. También soporta además los formatos de Video CD, Super Video CD y DVD.

13 octubre 2005

Un chat en java

En http://www.geocities.com/xtr3m3_sc0rpi0/java/chat/ hay el código de ejemplo de un chat en java. No lo he probado, pero tiene pinta de ser un código sencillo y que sirve perfectamente de ejemplo.

09 octubre 2005

Entornos y herramientas para desarrollo de software

En Entornos y herramientas para desarrollo de software hay un montón de enlaces a herramientas de programación:

- Herramientas case, para dibujo uml
- Editores configurables
- Herramientas para "navegar" por el código
- Compiladores varios
- Análisis de código (métricas y demás)
- Cosas de ambiente unix sobre windows

En fin, un poco de todas aquellas cosas que en algún momento hemos necesitado y que hemos tenido que buscar como hemos podido.

05 octubre 2005

El fin de fichero en C

Una pequeña tontería que suele despistar al principio.

Cuando leemos un fichero en C, normalmente leemos hasta que encontramos el fin de fichero, con la función feof(). Lo normal es hacer un bucle de este estilo

while (!feof(fichero))
{
...
}

El problema que no todo el mundo sabe es que feof() es cierto sólo cuando intentamos leer después de acabar el fichero.

Si el fichero está vacío y hacemos esto

fichero = fopen (...);
while (!feof(fichero))
{
fread (...);
tratarLeido(...);
}

abrimos el fichero. Como no hemos intentado leer, feof() es false y leemos datos. No hay datos que leer, fread() devolverá un error (que solemos ignorar) y tratamos los datos que no hemos leidos. En el siguiente bucle, como ya hemos intentado leer después de fichero, feof() es true y se acaba el bucle.

Si hubiera datos, trataríamos todo bien, pero después de leer los últimos datos y tratarlos, feof() sigue siendo false. Intentamos una nueva lectura fallida y tratamos los datos que no hemos leido.

La forma correcta de hacer este bucle, es hacer una lectura ANTES de mirar la condición feof(). Es decir

fichero = fopen(...);
fread (...)
while (!feof(fichero))
{
tratarLeido(...);
fread(...);
}

De esta forma, inmediatamente después de leer se hace la comprobación de si hemos obtenido el feof() y si no es así, tratamos el dato.

04 octubre 2005

Las cosas de Windows

Con el cuento de la tarjeta aver media, tuve que reinstalar windows desde cero. Como tenía prisa por ver si se me repetía el problema, no di de alta ningún usuario.

Más adelante, resuelto el tema de la tarjeta, me decidí a dar de alta algunos usuarios (el de jugar con internet, el de hacer programas, etc). Todo decidido, le doy a "inicio", "configuracion", "panel de control", "usuarios y contraseñas" y me creo los usuarios.

¡Sorpresa!. Cuando intento entrar como uno de los usuarios recien creados, no puedo. Da error de que no se puede copiar la configuración local en c:\Documents and Settings\usuario. Veo que dicho directorio no se ha creado. Creándolo a mano, se obtienen nuevos errores.

Me voy a consultar internet y resulta que los usuarios se dan de alta en el icono de "Mi PC", con el botón derecho del ratón, sacamos el menú y le damos a "Administrar" y "usuarios locales y grupos", "usuarios", nuevamente botón derecho y "nuevo usuario". Haciéndolo así, funciona todo correctamente.

¿Para que sirve el "usuarios y contraseñas" del panel de control? Misterio.

03 octubre 2005

Meter todo nuestro programa java en un solo jar

A veces hacemos un programa java que tira de otros jar externos. Por ejemplo, si hacemos un programa de base de datos contra oracle, necesitamos el jar con el driver de oracle, es decir, el ojdbc14.jar. También podemos usar para sacar nuestros mensajes de error el log4j, y necesitamos el jar correspondiente log4j.jar

Cuando metemos nuestro programa en un jar, en nuestro fichero de manifiesto podemos poner que necesitamos esos jar externos. Sería algo como esto

Manifest-Version: 1.0
Class-Path: ./ojdbc14.jar ./log4j.jar
Main-Class: MiPaquete.MiClasePrincipal


Esto va más o menos bien. El problema es que junto con nuestro jar debemos entregar los otros jar. Es decir, nuestra aplicación está compuesta de tres jar, el nuestro, el de la base de datos y el del logger.

Hay una librería de sourceforge que permite empaquetar esos jar externos dentro de nuestro jar. De esta forma, dentro de nuestro jar meteríamos también el ojdbc14.jar y el log4j.jar, junto con nuestras clases.

De esta forma, nuestra aplicación se entregaría en un único MiPrograma.jar. Todos los demás jar necesarios estaría dentro.

Aunque no lo he probado todavía, parece que simplemente hay que bajarse el one-jar-boot.jar. Al desempaquetarlo salen varias clases y un fichero de manifiesto boot-manifest.mf. Ahora sólo tenemos que añadir a nuestro jar esas clases y ese nuevo fichero de manifiesto. Con ello, nuestro jar buscará los jar que indiquemos en el atributo "Class-Path" de nuestro fichero de manifiesto original, dentro del jar y no en el disco duro.

29 septiembre 2005

Picasa

Otro programita más de google basado en lo mismo, en buscar.

Nos descargamos este programa, lo instalamos, lo ejecutamos y se dedica a buscar todas las fotos y videos que tengamos en nuestro PC.

Por defecto nos muestra todos los directorios que tienen fotos ordenados por fecha, de más reciente a más antiguo.

En la parte del buscador ponemos palabras y según vamos escribieno, van desapareciendo todos los directorios y fotos que en su nombre no tienen eso que vamos escribiendo.

A cada directorio podemos ponerle un texto asociado, indicando, por ejemplo, qué cosas hay en las fotos, dónde están hechas, etc. El buscador luego tendrá también en cuenta estas palabras. Si tenemos la paciencia de poner estos textos a cada directorio con fotos, luego es muy sencillo encontrar las fotos de las vacaciones, de las bodas, etc.

26 septiembre 2005

Aver Media AverTV 203

Esta fin de semana he estado instalando la tarjeta Aver Media AverTV 203 para ver la tele en el ordenador. No cogí la AverTV Studio 203, porque la única diferencia es que esta última tiene para escuchar la radio y es algo más cara. No voy a escuchar la radio con el ordenador en la vida.

Mis problemas con la instalación.

La instalación resultó "sencilla". En primer lugar hay que instalar el driver desde windows. Esto es lo primero que desconcierta, porque normalmente esperamos que en el CD de la tarjeta venga un programa que lo instale todo solito. Pues no, el driver hay que instalarlo desde windows, diciéndole a windows que busque en el CD.

Luego se instala el programa. Todo funcionó correctamente.

Sin embargo, tuve un "pero". Cuando dejé de jugar con la tarjeta y me decidí a apagar el ordenador, se quedó colgado. Tuve que apagarlo de mala manera. Luego no volvió a encender. Cuando intentaba arrancar windows, salían rápidamente unos mensajes de error que no se podían ver, se quedaba la pantalla negra y el ordenador bloqueado.

Intenté arrancar en modo a prueba de fallos. Nada de nada. Al final reinstalé windows desde cero. Luego volví a intalar la tarjeta y esta vez, casi sin problemas.

Primero instalé la tarjeta gráfica. Luego la AverTV, que me da un aviso de que la tarjeta de sonido no está accesible (todavía no la había instalado). A pesar de todo se hacía la instalación, pero al arrancar el programa de televisión, daba un error y se cerraba.

Instalé la tarjeta de sonido y el programa averTV ya funcionó .. con la pantalla en negro. Tras darle vueltas descubrí que si no pones a windows en modo de muchísimos colores, simplente sale la tele negra y no se ve nada, aunque se oye.

Ya está, seguí instalando todo lo demás y todo bien.


Mi opinión sobre la tarjeta AverTV

Por lo demás, la tarjeta muy bien.

El driver WDM que comenté en el post anterior debe venir con windows, porque no me hizo falta instalarlo a posta y el programa de ver la tele es capaz de grabar directamente en mpeg-ii y formato dvd.

En la caja ponía que grababa también el divx si se disponía del codec ... y es cierto. Es más, por lo que he visto es capaz de grabar con cualquier codec que tengamos instalado. Dispone de los formatos mpeg-i, mpeg-ii, vcd, svcd y dvd. Luego además dispone de un formato avi manual, en el que elegimos el codec tanto para video como para sonido que queramos. Aquí es donde se puede elegir el divx.

En cuanto al programita tiene una cosa que me pareció curiosa (no sé si es útil), que consiste en que se puede poner la televisión como fondo de escritorio. Podemos trabajar mientras vemos nuestro canal favorito como fondo de escritorio. Digo que no sé si es útil porque yo normalmente hago grandes las ventanas con las que trabajo y casi nunca veo nada del fondo de escritorio.

Resumiendo

Salvo mis problemas de instalación que achaco más a windows que a la tarjeta de televisión, me gusta más esta tarjeta que la pinnacle pc tv pro.

22 septiembre 2005

WDM Video Capture Driver

En su día me dejaron una tarjeta Pinnacle PC TV Pro (o algo así) para ver la tele en el ordenador y poder grabar los programas.

Al intentar grabar en mpeg II, la opción siempre estaba deshabilitada. Mirando en la caja ponía que se podía grabar en mpeg II directamente, pero en esa indicación ponía un par de asteriscos. En la misma caja, buscando el significado de los asteriscos, ponía que la característica de poder grabar en mpeg II debía activarse por internet y pagando.

Ayer compré una AverMedia AverTV 203. Pone también lo de que graba en mpeg II con un par de asteriscos. Sin embargo, esta vez los dos asteriscos significan algo así como que sólo graba en mpeg II con el WDM Driver disponible para windows 2000, xp, ...

Miré en internet qué era el WDM driver ese y es simplemente un programa de la gente de sourceforge. Este programa únicamente es un driver que entiende determinadas tarjetas, basadas en los chip bt848, bt849, ... y que debe ser capaz de hacer la codificiación en mpeg II en tiempo real (con un micro lo suficientemente potente).

Esto me hace pensar que casi cualquier tarjeta basada en estos chips, incluida la Pinnacle que me dejaron, puede grabar en mpeg-II. Basta con instalar este driver y que el programa de captura que usemos dé la opción de grabar mpeg-II. Sé también que hay programas de captura gratuitos para este tipo de tarjetas, así que si el de la tarjeta no nos vale, podemos bajar uno de estos.

Este fin de semana instalaré la tarjeta AverMedia, el WMD driver y a ver qué pasa.

20 septiembre 2005

Look and Feel en java

Con java es muy fácil cambiar el aspecto (skin) de nuestras ventanas para que tengan aspecto java, aspecto windows, etc. Basta con tener la librería adecuada y una sola línea de código.

En javootoo.com hay un montón de look and feel (skins) para las ventanas distintos. En concreto me ha llamado la atención el Napkin Look & Feel, que hace que nuestras ventanas parezcan hechas a mano sobre una servilleta.

Basta con añadir el napkinlaf.jar correspondiente a nuestro proyecto y en el main añadir las líneas

try
{
UIManager.setLookAndFeel("napkin.NapkinLookAndFeel");
}
catch (Exception e)

{

e.printStackTrace();
}


El resultado, al arrancar nuestro programa java, puede ser como el de la imagen.






De todas formas, está en versión beta y aunque con un programa sencillo me ha funcionado bastante bien, he tenido problemas con los JDesktopPane y los JInternalFrame. Parece que no se refrescan bien o lo suficientemente rápido.

Los punteros de java

Hay un par de ideas sobre java muy extendidas: java no tiene punteros y en java todo se pasa por referencia.

La realidad, es que java se entiende mucho mejor si lo pensamos exactamente al revés. En java sólo hay punteros (con excepción de los tipos primitivos) y en java todo se pasa por valor (por copia).

Por ejemplo, en C++ hacemos esto

MiClase a;

y ya está todo correcto. La variable a está perfectamente inicializada. Si en java hacemos eso, tenemos una variable a sin inicializar. Es necesario hacerle un new, exactamente igual que un puntero en C++

MiClase a = new MiClase(); // Esto en Java
MiClase *a = new MiClase(); // Esto en C++

// o este otro tipo de inicialización extrañamente parecida ...

MiClase a = null; // en java
MiClase *a=NULL; // en C++

La única diferencia es la notación con el asterisco. Si pensamos que en java TODO son punteros, no es necesario poner el asterisco para distinguir lo que es puntero de lo que no lo es, por lo que símplemente lo han quitado.

Ahora imaginemos un método que recibe una clase y que le hacemos una llamada

// en java...
void medodo (MiClase a)
{
a = new MiClase();
}
...
MiClase b = null;
metodo (b);

Bueno, pues cuando salimos del método b sigue valiendo null, "apuntando a null". Eso quiere decir que a y b son variables disintas, es decir, se ha pasado la variable b por valor al método.

¿Cómo podemos crear una nueva instancia y devolverla?. En java no queda más remedio que hacerlo en el return, es imposible hacerlo a través de parámetros. Sin embargo, en C++ tenemos más posibilidades. Podemos usar un puntero al puntero, es decir, hacer esto

void metodo (MiClase **a)
{
*a = new MiClase();
}
...
MiClase *b=NULL;
metodo (&b);

o bien, incluso usar referencias de verdad

// El & en la declaración es lo que hace que realmente sea una referencia.
void metodo (MiClase * &a)
{
a=new MiClase();
}
...
MiClase *b=NULL;
metodo (b);
// Aqui b apunta al MiClase creado dentro del método.

Haciéndolo así, el puntero b de fuera del método y el puntero a del parámetro son exactamente la misma variable. Ojo, no quiero decir que sean dos punteros distintos que apunten al mismo lado, sino que son realmente el mismo puntero. Cuando hacemos que a apunte a otro sitio, b también apuntará al mismo sitio. Esto es lo que yo entiendo realmente por referencia.

Vemos en este sentido que C++ nos da más posiblidades que java.

19 septiembre 2005

Memorias de un aprendiz de PHP

En http://www.rinconastur.net/php/index1.php hay una especie de tutorial de apache, php y mysql.

Tiene bastante buena pinta y comienza desde el principio, instalando estos programas en windows.

El autor advierte que no es un manual sino que "estas «Memorias» solo son apuntes a pie de obra..., notas que he ido confeccionando día a día a medida que intentaba ir aprendendiendo."

17 septiembre 2005

Uso rápido del JTable

Veo en muchos foros que la gente pregunta cómo manejar el JTable. Voy a tratar de contar el uso más sencillo que deja libertad para modificar luego los datos sobre la marcha.

Para usar tablas, hay que distinguir dos cosas. Por un lado tenemos el JTable, que es lo que vemos. Por otro lado tenemos los datos, que es lo que queremos pintar en el JTable. Los datos pueden guardarse en cualquier clase que implemente TableModel. Java nos ofrece DefaultTableModel, una clase que implementa TableModel y nos permite añadir, modificar y borrar esos datos.

La forma sencilla de juntar todo esto es

DefaultTableModelo datos = new DefaultTableModel();
JTable tabla = new JTable(datos);

y ya está.

Ahora podemos añadir columnas a nuestros datos llamando a

datos.addColumn ("Nombre columna");

y podemos añadir, borrar y modificar

datos.addRow ( arrayConLosDatosParaUnaFila );
datos.removeRow ( fila );
datos.setValueAt (dato, fila, columna);

Echando un ojo en la API de DefaultTableModel, veremos muchos más métodos que pueden ser útiles.

Tengo un tutorial más completo sobre el modelo de datos en http://www.chuidiang.com/java/tablas/tablamodelo/tablamodelo.php

También se puede cambiar el cómo pintar los datos o cómo editarlos. De esta forma podremos poner iconos en las celdas, hacer que salgan coloreadas o bien que al hacer doble click sobre ellas se editen con un JComboBox o cualquier otra ventana que se nos ocurra.

16 septiembre 2005

Un pequeño problema con Swing

Conozco a varias personas, incluida yo, que han tenido un pequeño problema con las tablas de Swing.

Supongamos que tenemos nuestro JTable y nuestro TableModel, bien el DefaultTableModel o bien uno hecho a medida. Como es natural, cuando modificamos datos en nuestro TableModel, se actualiza automáticamente el JTable. Esto se debe a que los TableModel implementan un mecanismo de suscripción a cambios. El JTable se suscribe a cambios en el TableModel, se entera cuando éste cambia y se refresca en pantalla.

Los repintados en pantalla se hacen todos en un hilo (thread) aparte, llamado hilo de awt. Cuando el JTable necesita ser repintado, por algún cambio en el TableModel, el hilo de awt comienza a preguntar al TableModel por sus datos para pintarlos en el JTable.

Ahora supongamos que tenemos un hilo independiente, lo voy a llamar hilo A, que se dedica de forma más o menos rápida a añadir y borrar datos del TableModel. Puede pasarnos y de hecho a veces lo hace, que ocurre la siguiente secuencia:
  • El JTable necesita ser repintado. El hilo de awt le pide al TableModel cuántos elementos tiene. Este, por ejemplo, dice que tiene 10.
  • El hilo de awt se mete en un bucle de i=0; i<10;>
  • El hilo independiente A, cuando el hilo de awt está en medio del bucle, le da por borrar el elemento número 9. El TableModel avisa por medio del mecanismo de suscripcion y el evento de cambio queda encolado hasta que el hilo de awt pueda atenderlo
  • El hilo de awt sigue con su bucle y cuando llega al tableModel.getValueAt (9, j), le salta una excepción de indice fuera de rango, el elemento 9 ya no existe. En la ventana el JTable puede quedarse en estado catatónico
Este problema pude comprobar que pasaba también con JList y DefaultListModel y supongo que es general. De hecho, se advierte que las clases de Swing no son seguras con multihilo.

Los synchronize no sirve de nada, puesto que el hilo de awt está en un bucle y hace varias llamadas al modelo, bloqueándolo y liberándolo consecutivamente. El hilo A puede colarse entre medias y borrar.

¿Cual es la solución?.

Solución 1.

La primera solución que se le ocurre a todo el mundo es que el hilo A añada y borre elementos usando SwingUtilities.invokeLater(). Esto hace que el añadido y borrado de elementos en el TableModel se encole para que lo haga el hilo de awt. Si el hilo de awt está en su bucle refrescando el JTable, no va a añadir ni borrar elementos hasta que termine.

Esta solución no me gusta demasiado. Hay que llenar el código de SwingUtilities.invokeLater() por todos lados y acordarse de hacerlo siempre. Además, el parámetro de éste método es un Runnable, por lo que todavía es más incómodo llamarlo.

Solución 2.

La solución que más me gusta es duplicar el modelo. Los datos no se duplican, así que no es un gasto excesivo de memoria. A uno lo llamo modelo_real y al otro modelo_awt. Una clase hecha una sola vez, se suscribe a cambios en modelo_real y los replica, usando SwingUtilities.invokeLater() en modelo_awt. El modelo_awt es el que se pasa al JTable y queda más o menos oculto para todo el mundo. El hilo A y cualquier otro sitio del código, deben trabajar con el modelo_real.

La ventaja de esta solución es que haciéndo una clase una sóla vez y quizás un TableModel para que nos haga de modelo_awt, ya no tenemos que volver a tirar código. Luego nadie debe acordarse de llamar al SwingUtilities.invokeLater().

La pega es que si alguien le pide el modelo al JTable, va a obtener un modelo que no es el de trabajo del resto del código y puede haber algun problema.

De hecho, me he hecho mi propia versión de JTable que redefine los métodos que tienen que ver con el TableModel (incluidos constructores). Yo uso mi JTable y le paso mi modelo_real. Mi JTable se encarga de instanciar la clase de réplica y el modelo_awt. El método getModel() devuelve el modelo_real. Ahora casi nunca uso un JTable directamente, sino MiJTable.

Métricas para eclipse

Me he instalado el JDepend4eclipse, un plug-in que da métricas sobre paquetes java.

Está bien en el sentido de que nos da las dependencias entre paquetes, y así podemos ver si nuestros paquetes están muy enrevesados (todos tiran de todos) o llevan más o menos una estructura de árbol en sus dependencias (hay paquetes independientes que no dependen de nadie, otros más complejos que dependen de los independientes y otros más complejos aun que dependen de los anteriores), que es lo lógico.

Sin embargo JDepend no da más métricas de clases ni las típicas de código (complejidad ciclomática, número de líneas, relacion código/comentarios, etc, etc), por lo que de momento lo veo un poco limitado.

Existe también un JDepend independiente de java, que me he instalado, pero da incluso menos información que el plug-in de eclipse. Realmente da la misma información que el plug-in, pero en el plug-in aparece además un gráfico grado de abstraccion/inestabilidad del paquete, que en JDepend no aparece. En dicho gráfico aparece cada paquete como un puntito verde, negro o rojo. Supongo que verde es que el paquete está más o menos en una zona adecuada, negro es una zona intermedia y rojo que ese paquete es desastroso.

15 septiembre 2005

Ejemplos de java

Cortesía de un compañero de trabajo, una página con muchos ejemplos de java, tanto j2ee, jsp, servlets, swing, patrones, etc, etc.

14 septiembre 2005

Propiedades de System.getProperty()

Hay muchas cosas relativas al sistema operativo que podemos obtener desde java.

En la API, si miramos la clase System y dentro de ella el método getProperties() tenemos un listado de unas cuantas.

Reproduzco aquí el listado de la version 1.4.2 de java, con algún comentario mio de los más útiles

java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path Util para crear ficheros temporales en /tmp o c:\tmp
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name Nombre del sistema operativo
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX) Separador de los directorios (unix es /, windows es \). De todas formas java entiende cualquiera de ellos
path.separator Path separator (":" on UNIX) Cuando en una variable, por ejemplo PATH, ponemos varios valores, el separador en unix de estos path es : mientras que en windows es ;
line.separator Line separator ("\n" on UNIX) Fin de linea. \n en unix, \r\n en windows.
user.name User's account name Nombre del usuario.
user.home User's home directory Directorio por defecto del usuario.
user.dir User's current working directory Directorio en el que está corriendo el programa java. Util para poner path relativos.

Tortoise CVS

Tortoise CVS es un programita que se integra con el explorador de windows.

Una vez instalado, cuando abramos nuestros directorios con el explorador de windows y navegemos por ellos, veremos que nuestros iconos de fichero están modificados. Esta modificación indica si el fichero está en cvs, si está actualizado, modificado, etc.

Pulsando con el botón derecho sobre el icono para ver el menú, saldrán más opciones de las habituales, dándonos opción a meter el fichero en CVS, editarlo, etc, etc.

Una herramienta que nos puede ayudar a los que trabajamos con CVS sobre windows.

Programación de C en unix

En http://www.cs.cf.ac.uk/Dave/C/ hay un tutorial (casi un libro) que explica la programación en C sobre unix.

Comienza explicando C, desde su historia hasta las funciones más tontas, pasando por los if ,for, punteros, etc, etc.

Luego comienza lo interesante, trata todos los temas específicos de unix, como IPC (semáforos, colas y memoria compartida), sockets, rpc, hilos, etc.

En fin, un buen tutorial en perfecto inglés.

13 septiembre 2005

Entrada standard en java

En java, para leer la entrada standard (la del teclado) contamos con System.in

Sin embargo, System.in es un InputStream, que cuenta con pocos métodos útiles para leer el teclado. De hecho, sólo tiene métodos para leer bytes. Si en el teclado escribimos una A mayúscula, System.in nos devolverá un byte 65.

Afortunadamente en java hay muchas clases ya preparadas. Tenemos clases InputStreamReader, BufferedReader, FileReader, etc. Estas clases tienen como misión leer un "flujo" de bytes o de caracteres y darnos métodos que nos faciliten la lectura.

Hay básicamente dos tipos de clases. Las más básicas son las InputStream, que son clases que leen bytes. Sobre ella se construyen los Reader, que son clases que leen caracteres (transforman los bytes a caracteres). Para convertir de una a otra, tenemos el InputStreamReader.

Un InputStreamReader recibe un InputStream en el constructor y se comporta como un Reader, es decir, lector de caracteres. La clase InputStreamReader tiene métodos que nos permite leer char o arrays de char.

Bien, con este trozo de código

InputStreamReader isr = new InputStreamReader(System.in);

ya tenemos un InputStreamReader asociado al teclado y del que podemos leer directamente caracteres, en vez de bytes. Cuando escribamos una A, leeremos una 'A' y no un byte 65.

La siguiente clase que podemos usar es BufferedReader. Esta clase recibe un Reader en el constructor (podemos pasarle nuestro InputStreamReader) y tiene un método para leer una línea completa de teclado, de forma que nos devuelve un String.

BufferedReader bf = new BufferedReader (isr);
String lineaTeclado = bf.readLine();

Estupendo, ya podemos leer líneas de teclado.

El problema ahora es si escribimos un 123, obtendremos "123" como String. Seguramente queramos convertirlo a int, o float o lo que sea. Para ello no nos queda más remedio que analizar la cadena y convertirla al valor que queramos. Por ejemplo, para convertirla a un int, podemos hacer esto

int valor = Integer.parseInt (lineaTeclado);

Por supuesto, se supone que hemos escrito un entero en esa línea y sólo un entero, o saltará una excepción.

El siguiente es un código de ejemplo con todo esto junto:

// Creación de BufferedReader para facilitar la lectura.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

try
{
// Lectura de un entero
System.out.print ("Introduce un número entero : ");
String cadena = br.readLine();
int valor = Integer.parseInt(cadena);
System.out.println ("Has escrito "+valor);

// Lectura de un double
System.out.print ("Escribe ahora un numero flotante : ");
cadena = br.readLine();
double valor2 = Double.parseDouble(cadena);
System.out.println ("Has escrito "+valor2);

} catch (Exception e)
{}

Entendiendo make y los archivos Makefiles

En http://www.ubiobio.cl/~gpoo/documentos/make/ hay un tutorial sobre los makefile.
Parece bastante clarito y va paso a paso.
Yo, por mi parte, tengo mi propia versión, un poco menos bonita y menos explicada en http://www.geocities.com/chuidiang/herramientas/makefile.html

Comandos de bash linux

En http://www.ss64.com/bash/index.html he encontrado un listado de comandos de bash de linux.
Pinchando en el comando aparece una ayuda sobre dicho comando.
Lástima que esté en inglés.

Notepad++ y gvim

He encontrado el Notepad++

Es el notepad de windows de siempre, pero mejorado para programación. En función de la extensión del fichero (.cpp, .java, .php, etc) es capaz de colorear las palabras reservadas del lenguaje, autosangrado, etc, etc.

Dicho de otra forma, una versión mejorada del notepad para programación.

De todas formas, vengo del mundo unix y el editor que más me gusta con diferencia es el vi (en sus versiones mejoradas, vim y gvim). También hay gvim para windows, entiende bastante más lenguajes de programación que el notepad++. Incluso es posible, por medio de ficheros de configuración (al menos en unix), crear tus propios lenguajes y coloreados (aunque no parece una tarea sencilla).

Dentro de linux/unix, con ayuda del comando ctags, se puede incluso navegar con el gvim dentro del código.

Actualmente programo con eclipse en java en entorno windows. Sin embargo, para muchas tareas de edición sigo abriendo el gvim, ya que tiene muchos comandos que echo de menos en los editores estilo windows.

Entiendo, sin embargo, que el vi es un editor odioso cuando se empieza y que para la gente acostumbrada al mundo windows, el notepad++ puede ser una buena alternativa.

Technorati: Home

En Technorati: Home he encontrado un buscador que busca en www.blogger.com. Ordena los resultados de búsqueda del más reciente al más antiguo.

La intención de este buscador es, por lo visto, que podamos ver las entradas más recientes sobre un determinado tema, para ver qué opina la gente o qué se cuece en la red.

12 septiembre 2005

firmar un jar

En http://www.vistoynovisto.com/vistoynovisto/Tutorial/Javatut2/jar/sign/index.html he encontrado un pequeño tutorial sobre como firmar y verficar ficheros jar firmados.

Es algo más detallado que la página de merenciano y supongo que la idea para los applets es muy similar.

Does XML Suck?

En su día, tras oir hablar continuamente de XML, decidí enterarme de qué era. Compré una guia de anaya, de esas baratas, titulada XML.

Tras enterarme qué era y aprovechando que en el trabajo empezabamos con java, me enteré de cómo se leen ficheros XML en java. De hecho, hay clases Java que vienen con el compilador para la lectura de dicho tipo de ficheros.

Dicho y hecho, nos pusimos a hacer código y en cuento teníamos posiblidad, usabamos ficheros XML.

Sin embargo, tras unos cuantos experimentos, empezó a entrarme la duda. ¿Realmente me aporta algo XML?. Me resultaba más fácil escribir mis ficheros en otro formato de texto (el que siempre había usado cuando trabajaba en C++) y tener mi clase java ya preparada para ese formato (al igual que la preparé en su día en C++).

Buscando por internet, he encontrado esta página (en perfecto inglés). En ella hay un articulo diciendo que XML es un asquito. Ese articulo ha ido evolucionando y al final dice que sigue siendo un asquito, pero se puede trabajar con él y hay que hacerlo porque todo el mundo lo hace. Hay las tres versiones del artículo mostrando la evolución en esa página.

En fin, salvo que me vea obligado o vea una ventaja clara, seguiré haciéndome mis ficheros de datos de la forma que más cómoda me resulte.

08 septiembre 2005

Primer mes sin wanadoo

Parece que he conseguido darme de baja de Wanadoo.

El mes de Julio me llegó una factura a medias (teóricamente de los días que estuve de alta en Junio hasta que me dieron efectivamente de baja).

Este mes de Agosto no me ha llegado factura de ellos.

07 septiembre 2005

Google Earth - Products

Acabo de descubrir GoogleEarth.

Es una aplicación que nos bajamos de http://earth.google.com/earth.html y nos presenta un mapa mundo desde lejos. Podemos acercarnos a cualquier punto del planeta hasta ver la foto por satélite de la zona.

Tenemos botones para girar e incluso tumbar la cámara. Si una vez tumbada avanzamos, es como si fueramos volando en avión sobre el mapa.

Además tiene el perfil del terreno, por lo que veremos las elevaciones del terreno.

Eso sí, se baja los mapas de internet sobre la marcha, según lo vayamos viendo, así que necesitamos una conexión rápida.

06 septiembre 2005

Me estoy quedando obsoleto

El otro día me instalé cygwin y ya de paso el gcc.

Me puse a hacer un típico "Hola mundo" en C++ y ¡sorpresa!, me da un warning de que

#include <iostream.h>

esta obsoleto, que en su lugar use

#include <iostream>

sin el .h del final.

Me pongo a hacerlo y me falla. Me lio a buscar en internet y resulta que hay que poner un "using namespace std" o bien un "std::cout".

En fin, el C++ va cambiando y yo me quedo atrás....

Merenciano.tk :: Ver tema - ¿Como firmar un Applet?

En http://usuarios.lycos.es/fady/foro/viewtopic.php?t=58&sid=3429077c5bc0afda79734122e41f17a3 he encontrado la forma de firmar un applet.

Los comandos que aparecen (keytool y jarsigner) son de java, así que no debería haber ningún problema.

Teóricamente un applet firmado tiene permiso para hacer más cosas que un applet sin firmar (siempre que le digamos al navegador que confíe en esa firma). De esta forma se pueden hacer applets que accedan al disco del usuario para guardar o consultar datos. Es algo que tendré que probar algún día.

Ya puestos, el foro de java en esa misma página tiene resueltas algunas de las dudas más comunes que aparecen en otros foros, por ejemplo, cómo empezar con java, crear un exe, etc.

03 septiembre 2005

cygwin

Yo siempre he trabajado en entorno unix. Me manejo mucho mejor con una shell de unix que con la ventana de ms-dos y para determinadas tareas, incluso mejor que con el ratón y el escritorio de windows.

Por ejemplo, cuando trabajo en java sin el entorno de desarrollo, echo mucho de menos el comando "find" de unix. Para compilar todos los fuentes de un directorio y sus subdirectorios, desde la shell hago algo como esto

javac `find . -name *.java`

Esto no se puede hacer en ms-dos, no queda más remedio que hacer cosas como

javac paquete1\subpaquete1\*.java
javac paquete1\subpaquete2\*.java

y así sucesivamente.

Por todo ello decidí bajarme una shell de unix para windows y así olvidarme, dentro de lo posible, de la ventana de ms-dos.

Me decidí por instalar cygwin, que en realidad es un entorno unix para windows. En esa página me bajé el setup e instalé lo que el me dijo por defecto. Con esto ya tengo una shell "bash".

Luego, corriendo nuevamente el setup, me bajé el ddd (debugger para C) y el gcc/g++ y el vim (el editor). Me arreglo mucho mejor con este compilador de C y el gvim que con el Visual C++.

Como conectar Java y Access

En un foro mencionan este artículo para conectar java con access.

El "truco" es establecer un DSN (Data Source Name), sabe Dios qué es eso.

Una vez hecho, el resto en nuestro programa java es como siempre. El driver a usar es "sun.jdbc.odbc.JdbcOdbcDriver" y la forma de obtener la conexion con

Connection con = DriverManager.getConnection("jdbc:odbc:Nombre_Perfil_DSN", "Nombre_Usuario", "Contraseña");

31 agosto 2005

Using HTML in Swing Components

En los JLabel, JButton y demás se puede poner una etiqueta normal de texto o bien código html.

El siguiente ejemplo:

import javax.swing.*;

public class prueba
{
public static void main(String[] args)
{
JFrame ventana=new JFrame();
JButton boton = new JButton ("<html>a<br>b/<html>");
ventana.getContentPane().add(boton);
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ventana.pack();
ventana.setVisible(true);
}
}

pinta una ventana con un botón con dos lineas de texto.

Hay un pequeño tutorial de esto aquí:

Using HTML in Swing Components

GMail API For Java (g4j)

Cortesía, nuevamente, de un compañero de trabajo, aquí hay un paquete de java que permite conectarse a gmail para ver el correo y demás.

http://g4j.sourceforge.net/

No lo he probado y no sé muy bien para qué puede servir (salvo para hacerse un cliente especifico de correo para gmail, que ya viene con la aplicación), pero bueno, no deja de ser una cosa curiosa.

Basándose en esta api, hay un plug-in para eclipse que permite desde eclipse ver el correo de gmail. Dice además que usa el puerto 80, con lo que podemos saltar cortafuegos que nos limiten los puertos. Yo por ejemplo, desde mi Thunderbird no puedo ver en el trabajo el correo de gmail porque gmail usa un puerto no standard y el cortafuegos de la empresa no me deja abrir esta dirección.

Administración de Sistemas Operativos

Echando un ojo en google me he encontrado un tutorial sobre socket, rpc.

Me ha gustado ver que han utilizado los tutoriales de mi página como referencia. Los han mejorado añadiendo figuras, eliminando mucha paja y algunos datos de interés más.

Se les puede echar un ojo para ver otra versión más seria y algo más completa de los que puse un día en mi página.

También tienen un tutorial sobre rmi, pero ese no parece tener mucho que ver con el que hice yo.

29 agosto 2005

Ficheros de inicio de unix

En un foro encontré un link bastante interesante:

http://www.cs.sonoma.edu/~rmamer/shells_and_init_files.html

En él está los ficheros de inicio que utilizan los distintos unix. Son los ficheros en los que debemos poner las variables de entorno que nos interesen, en función de si queremos que afecten a todos los usuario, sólo a un usuario etc.

Aparecen ksh de solaris, csh de solaris, bsh de solaris, tcsh de solaris, ksh de linux, csh de linux, bash de linux y tcsh de linux.

Básicamente se ejecuta un fichero en /etc/ que es el que afecta a todos los usuarios. Según la shell que sea, puede ser profile, .login, chs.cshrc o csh.login. Luego se ejecuta uno en el HOME del usuario y sólo le afecta a él. Según la shell que sea, puede ser .profile, .cshrc, .login, .bash_profile, .bashrc, etc.

En el link mencionado tienes una lista completa.

23 agosto 2005

http://www.java-source.net/

Un compañero de trabajo me ha mandado esta página: http://www.java-source.net/

En ella hay un montón de programas java gratuitos bastante interesantes.

Aparecen varios IDE de java, como eclipse y netbeans además de otros (JEdit, BlueJ, etc, etc). Hay servidores de chat, de foros, clientes de bases de datos, etc, etc, etc.

En fin, una página interesante de consultar cuando necesitemos algún programa gratis.

20 agosto 2005

Internacionalización de java

En http://www.programacion.com/java/tutorial/i18n/ hay un tutorial sobre la internacionalizacion de java que tiene buena pinta.

El problema básico de la internacionalización consiste en conseguir que nuestro programa muestre los textos en español, en inglés, en frances, etc en función de quién los esté leyendo. Esto también incluye el presentar los números con coma decimal o punto, unidades monetarias, etc, etc.

Si mostramos los textos directamente en código, para cambiar de idioma deberíamos rehacer y recompilar el código. Esto, por supuesto, es bastante engorroso.

La solución que propone java es escribir todos esos textos en un fichero de propiedades, es decir, un fichero de texto que contiene algo parecido a esto para español

saludo=hola
despedida=adios

o a esto en inglés

saludo=hello
despedida=bye

El programa java debe leer el fichero adecuado según el idioma y mostrar los textos que en él se indican, el de saludo y el de despedida en este caso.

Java, con sus clases ResourceBundle y asociadas facilita todas estas tareas, de forma que el ficheor de propiedades adecuado se puede cargar automáticamente en función del idioma elegido para el sistema operativo (windows o el que sea) y se muestran automáticamente los textos en dicho idioma.

12 agosto 2005

Ocultar IP

Un problema que me han planteado es el de ocultar la ip mientras navegamos, de forma que podamos engañar a esas páginas que recogen estadísticas de las ip que las visitan.

En http://www.comodescargar.com/trucospc/ocultar-ip-manual.html hay un pequeño manual que indica varias posibilidades.

Básicamente ha visto que consiste en navegar usando un proxy, de forma que en la página web que visitamos se ve la dirección ip del proxy y no la nuestra. En internet existen proxy gratuitos con los que nos podemos enchufar (por ejemplo, 212.7.14.177 en el puerto 80, que es una dirección de Estonia).

El programa "Hide ip Platinum" lo que hace es precisamente eso, configurar nuestro navegador (internet explorer) para que use un proxy. Incluso cambia de proxy a petición, de forma que en varias visitas sucesivas podriamos aparentar ser ip disitintas. De todas formas, me he descargado el programa y he tenido problemas al navegar con algunas de los proxy que me ponía. Supongo que eso no es culpa del programa, sino de la disponibilidad del proxy en cuestión.

También he probado a desinstalar el programa "hide ip platinum" y configurar el navegador a mano con uno de los proxys y funciona también.

10 agosto 2005

Cargar imagen de un jar

En http://www.javahispano.org/faq.thread.action?forum=108&thread=1969990118&id=1969990118 hay una contestación en un foro sobre como cargar una imagen de un fichero jar desde un programa java.

Por supuesto, tal cual esta vale si imagen.gif esta en el "directorio raiz" del jar, es decir, si no está empaqueta en algún subdirectorio.

Si hemos creado dentro del jar un subdirectorio iconos o imagenes para meter la imagen, deberemos poner el path.

Image miImagen = getImage (getClass().getResource ("imagenes/imagen.gif"));

También es importante que la clase en la que hagamos el getClass() esté dentro del mismo jar.

28 julio 2005

jace

En el foro de linux de la web del programador, "El Mogur" comenta la existencia de JACE, una librería de C++ standard que hace mucho más fácil el uso de JNI.

Nos la podemos bajar de http://sourceforge.net/projects/jace/ y tenemos documentación sobre ello en http://reyelts.dyndns.org:8080/jace/release/docs/guide/guide0.html

Bueno, otra cosa más pendiente de que le eche un ojo en algún momento.

27 julio 2005

Wanadoo

Parece que sí estoy dado de baja de wanadoo. Aparte de que me lo han confirmado telefónicamente, este mes me ha llegado una factura parcial de ellos, correspondiente al 1 de Junio al día que ellos dicen que me han dado de baja, 19 de Junio.

No sé si he tenido suerte o que la nueva normativa parece que se la tienen que tomar algo más en serio.

QT

Me han mandado un correo preguntando sobre un tutorial de socket para QT. Desgraciadamente no he podido contestar, no conozco ninguno.

Sin embargo me he puesto a mirar qué es eso de QT. Parece que es un entorno de desarrollo de C++ que permite ejecutar los programas en plataformas distintas. Es decir, podemos hacer nuestro programa con QT en windows y luego ejecutarlo en linux. Supongo que habrá que tener instalado QT en ambas plataformas, o como mínimo su versión de runtime, si es que la tiene.

El entorno de desarrollo es de pago, pero creo que merece la pena echarle un ojo. Es una nueva tarea que me apunto como pendiente....

22 julio 2005

14 julio 2005

Una tontería de C en linux

Viendo una pregunta en un foro, recordé un pequeño problema que tuve en su momento con C en Solaris (unix de Sun) y que nos trajo de cabeza a mí y a unos compañeros mios bastante tiempo.

El problema es que los decimales desaparecian al echar cuentas. Un programa tan tonto como este

main()
{
double a=5.4;
double b=0.1;
cout << a-b << endl;
}

daba de resultado 5, en vez de 5.3. Los decimales desaparecían. El problema era la variable de entorno LANG. Estaba definida por defecto a es (de español)

LANG=es;
export LANG;

Esto hacía que el compilador se liara. Consideraba que el punto decimal debía ser la , en vez de el . y de alguna forma, ignoraba los decimales.

Simplemente cambiándola por

LANG=c
export LANG;

y volviendo a recompilar el programa... ¡Todo arreglado!

log4j

He empezado a utilizar log4j.

Es una librería que permite escribir textos en pantalla, de forma similar a System.out.println(), desde un programa java. Sin embargo, va más allá. Luego, sin andar tocando por todo el código donde hemos escrito un texto, podemos hacer que determinados textos no salgan en pantalla, o que salgan por otro sitio (escribirse en una base de datos, salir en una ventana, etc).

Por ejemplo, si hacemos un algoritmo matemático en java y queremos ver resultados parciales en pantalla, podemos sacarlos usando esta librería e indicando que son de "depuración". Cuando alguna cuenta no nos cuadre, podemos sacar el texto indicando que es un "error". Podemos a la vez sacar mensajes parciales para el pintado de un gráfico, también como "depuración". Luego, al ejecutar y sin tocar código, podemos hacer que solo se vean los de "depuración", o sólo los de "error" o sólo los del algoritmo matemático, sean de "error" o de "depuración", pero no los del gráfico.

El filtrado puede ser más fino incluso. Podemos querer ver sólo los mensajes de "error" que escribe una determinada clase.

Para el uso de esta librería, además de bajarnos el jar correspondiente y añadirlo en nuestro classpath, debemos, en el main(), inicializar el "logger" con algo como esto:

PropertyConfigurator.configure ("fichero_configuracion");

Luego, en el código, para escribir mensajes, en vez de System.out.println(), escribimos cosas como esta:

Logger.getLogger(MiClase.class).debug("Esto es un mensaje de depuracion");
Logger.getLogger(OtraClase.class).error("Esto es un mensaje de errror");

El fichero de configuración que pasamos al principio es un fichero de propiedades de los de java y en él es dónde se indican qué mensajes se quieren ver: de qué clases, si los de depuración, los de error, los warning, etc.

En fin, igual de cómodo pero mucho más versátil que el System.out.println().

08 julio 2005

consulta de sql

Un pequeño truco tonto que he aprendido.
A veces tenemos dos consultas a bases de datos sobre tablas distintas, pero que nos dan bastantes campos comunes. Sin embargo, en una de las consultas aparecen, por ejemplo, un par de campos distintos que en la otra.
Supongamos que queremos una tabla de deportistas. Los datos de ellos son comunes, pero la mejor marca es distinta en función del deporte que hagan: para corredores, la mejor marca va en segundos, en minutos, etc. Para los saltadores de longitud y altura, va en metros y para los gimnastas son puntos. Imaginemos que los select que hay que hacer son de este estilo

select nombre, deporte, mejor_tiempo... para los deportistas
select nombre,deporte,mejor_distancia... para los saltadores
select nombre,deporte,mejor_puntuacion para los gimnastas

Imaginemos también que queremos meter todo esto en la misma tabla y que nos interesaría que los ResultSet que devuelve java tuvieran las mismas columnas, para tratarlos igual.

El truco consiste en que podemos poner null en los campos seleccionados en la consulta, de forma que nos devolverá null en esas columnas. De esta forma, con estas consultas

select nombre, deporte, mejor_tiempo,null,null ...
select nombre,deporte,null,mejor_distancia,null ...
select nombre,deporte,null,null,mejor_puntuacion ...


Nos devolverán el mismo tipo de ResultSet, pero con los "huecos" ya preparados cuando un determinado campo no tiene sentido. Los tres ResulSet podemos tratarlos con el mismo código y añadirlos fácilmente a la misma tabla.

Por supuesto, este "truco" tiene sentido si mejor_tiempo, mejor_distancia y mejor_puntuacion pertenecen a tablas de base de datos distintas que estén ligada a la tabla de deportistas. Si todo fueran campos de la misma tabla, los huecos ya estarían en la tabla y lo arreglaríamos fácilmente con una única consulta

select nombre,deporte,mejor_tiempo, mejor_distancia, mejor_puntuacion ...

21 junio 2005

Wanadoo

Después del nuevo reglamento para las operadoras telefónicas y de internet, decidí dar una segunda oportunidad a los de wanadoo para darme de baja.

Envíe el 2 de Junio un segundo fax al 90201009 solicitando la baja del servicio de tarifa plana que tenía con ellos (heredado de auna y a su vez heredado de retevisión).

Quince días después de enviar el fax, plazo en el que se supone que deben darte de baja, y al ver que sus teléfonos de consulta dejaron de ser de tarificación adicional (los 902 son de pago, pero a coste similar al de llamada local), decidí llamar para ver cómo iba el tema de la baja.

La primera sorpresa es que me atendieron relativamente rápido. Tuve que esperar un poco con la musiquita de marras, pero apenas fue un minuto. Según el operador que me atendió, me han dado de baja desde el 19 de Junio. Debe llegarme un recibo en Julio con el servicio correspondiente a Junio, desde el 1 al 19.

En fin, a ver si se es verdad que me llega ese mini-recibo y no me llegan más. Espero que con la nueva regulación hayan, por fin, empezado a mejorar las cosas.

Por cierto, desde que envíe el primer fax (en Febrero) solicitando la baja, me llamaban día sí, día también los de wanadoo para ofrecerme adsl. Cuando por Abril empecé a cabrearme con el tema, aproveché para echar la bronca a todos los de Wanadoo que me llamban para ofrecerme ADSL.

ant

Ant es una herramienta que ayuda al compilado de programas java, así como a realizar varias tareas como generar el javadoc, limpiar, llevar los jar a su sitio para la ejecución, etc, etc.

Con proyectos grandes (alrededor de 4000 clases) he tenido el problema de que al compilar con ant me daba un OutOfMemory error. Mirando en internet, encontré esta página http://confluence.public.thoughtworks.org/display/CC/OutOfMemoryError, en la que encontré una solución que me funcionó.

Basta con poner una variable de entorno ANT_OPTS con valor -Xmx1024m, de esta forma a la máquina vritual que usa ant se le da un giga de memoria, en principio más que de sobra.

10 junio 2005

eclipse

LLevo un tiempo programando con eclipse y mis conclusiones son las siguientes:

Por un lado, tiene muchas cosas buenas y útiles. Me gusta que arregle los import, eliminando los que no sirven. También que los añada automáticamente. Que cuando haya un error dé opciones de arreglo, de forma que eligiendo una se hace el arreglo solo. Tiene historia de los cambios que hemos ido haciendo, así podemos volver a una versión anterior sin CVS, etc, etc.

Sin embargo, sigue sin gustarme la forma de hacer los proyectos. No me acaba de convencer el compilado automático, no por el compilado en sí, sino porque a veces no hay forma de que recompile. Pulsando "clean" no hace caso. Mirando, mirando, acabé descubriendo que se debe a un error en la forma de crear el proyecto, pero por ningún lado sale el aviso indicándolo.

También me sucede con cierta frecuencia que se va la memoria y me toca reiniciar eclipse (el proyecto que manejo es grande).

Seguiré de momento con eclipse, puesto que arranca bastante más rápido que netbeans y me siguen gustando más las opciones de edición que me da. De todas formas, me han comentado de otro entorno, intellij idea, que miraré a ver qué tal.

03 junio 2005

UML y desarrollo orientado a objetos

Un link que parece interesante sobre uml y una metodología de desarrollo orientado a objetos.

Es un pdf en el que hay un resumen bastante explicado sobre UML y qué pasos dar para desarrollar un proyecto.

Aunque leí el libro "UML y patrones. Introducción al análisis y diseño orientado a objetos" de Craig Larman hace tiempo, la parte del pdf que habla de desarrollo de un proyecto parece un resumen de dicho libro.

wanadoo

He intentado darme de baja en wanadoo. Mandé el dichoso fax en Marzo y todavía siguen pasandome recibos.
Aprovechando que con la nueva normativa los teléfonos de consulta ya no son 800 de pago, llamé por teléfono. Me dicen que no habían recibido el fax, que lo volviera a enviar.
Lo volví a a enviar ayer, esperaré quince días (es el plazo que dicen ellos que tardan en darte de baja) y volveré a llamar. Si esta vez tampoco "lo han recibido", iré directamente al banco a decir que no paguen más.

01 mayo 2005

eclipse

Muy a pesar mio, me he pasado de netbeans a eclipse.

Aunque me gustaba mucho más la forma de "montar" proyectos de netbeans, un compañero de trabajo empezó a usar eclipse y viéndolo trabajar con él, he visto que tiene bastante más cosas que netbeans.

Tarde una mañana en conseguir montar mi proyecto adecuadamente. Como ya indiqué en algún comentario anterior de este diario, todo es muy fácil si empiezas de cero y pones tus fuentes donde te dice el entorno de desarrollo, pero es muy dificil si ya tienes tus fuentes creados y en una estructura que no se parece a la que necesita el entorno de desarrollo. Es posible hacerlo, pero me costó encontrar las opciones ocultas en los miles de ventanas con miles de pestañas que hay para configurar un proyecto.

Algunas de las cosas que me han gustado:
  • Indica qué imports no se utilizan, aparte de que si se le pide los pone automáticamente según vamos utilizando clases.
  • Permite corregir más rápido las cosas, por ejemplo, pinchando sobre el error nos da una lista de posibles correcciones y seleccionando una de ellas se realiza automáticamente.
  • Permite tener varias configuraciones para el arranque de cada programa, variables de entorno, parámetros que se pasan a la máquina virtual, etc, etc. De esta forma se puede arrancar el mismo programa con varias configuraciones.
En fin, seguiré con él de momento y a ver qué tal.