lunes, 27 de junio de 2011

Excluir librerías del jar con NetBeans

Este post sirve de continuación al que escribí hace casi un año, explicando cómo incluir las librerías de nuestro proyecto en el jar generado por NetBeans. En este caso, y por petición del amigo Anómino a través de los comentarios, vamos a ver cómo excluir librerías.

La clave para hacer lo que queremos está en la etiqueta zipgroupfileset del build.xml. Con este elemento le indicamos al entorno qué queremos añadir al jar que generamos. En aquél caso indicábamos que queríamos meter todos los jar de la carpeta dist/lib.


Ahora se nos presentan dos opciones para quitar elementos. El primero es indicar explícitamente qué librerías no nos interesan en el mismo zipgroupfileset utilizando su atributo excludes.


En este caso, como puede verse, le estamos indicando que no incluya la librería beansbinding.

Si necesitamos dejar fuera más de una, podemos añadirlas separándolas por un espacio.



Como segunda alternativa, en lugar de pedir que se incluyan todas, y luego añadir excepciones, podemos meter un elemento para cada una de las librerías que queramos tener en el jar de la aplicación, de la siguiente forma.


O, igual que antes, podemos tener un único elemento con todas las librerías a incluir separadas por espacios.



En conclusión, que para determinar exactamente qué librerías queremos en el jar de nuestra aplicación no tenemos más que jugar con los atributos includes excludes, y podremos conseguir lo que nos interese.

martes, 21 de junio de 2011

Componente para reproducir vídeos en JavaFX 2

Continuando con el nuevo JavaFX, he empezado a trabajar con la reproducción de contenido multimedia.

Lo primero que hay que resaltar, es que esta nueva versión de JavaFX, al menos por el momento, viene muy limitada al permitir sólo la reproducción de vídeo en formato FLV (que contenga vídeo en formato VP6 y audio en formato MP3).

Tal como se describe en la página de JavaFX, las clases implicadas en la reproducción de vídeos son:

Media - contiene información sobre el recurso, como su fuente, resolución y metadatos.
MediaPlayer - proporciona los controles para la reproducción (arranque, pausa, volumen...)
MediaView - extiende de nodo, y aporta la posibilidad de añadir animaciones, efectos...

Así que podemos reproducir un vídeo FLV con el siguiente código.

media = new Media(mediaPath);
   player = new MediaPlayer(media);
   view = new MediaView(player);
  getChildren().add(vbox);
   player.play();
Partiendo de esta base, he creado un pequeño componente que implementa un reproductor de vídeo sencillo, con posibilidad de pausar, avanzar, retroceder, ir a una posición concreta, y de cambiar el volumen. La clase extiende de javafx.scene.layout.Region, de forma que puede añadirse directamente al layout de una aplicación. Por ejemplo:

public void start(Stage primaryStage) {
     Group root = new Group();
        
     border = new BorderPane();
     border.setCenter(new VideoPlayer(videoPath);
        
     root.getChildren().add(border);
     Scene scene = new Scene(root, 800, 600);
           
     primaryStage.setScene(scene);
     primaryStage.setVisible(true);
  }
A la hora de indicar la ruta del vídeo que se quiere reproducir es importante tener en cuenta que no se admiten espacios; en su lugar tenemos que poner %20. Por ejemplo: 

C:/Documents%20and%20Settings/user/Mis%20documentos/1.flv

Aquí se puede descargar el VideoPlayer.

lunes, 6 de junio de 2011

InstantiationException

En cuanto uno empieza a hacer cositas con reflexión en Java, es normal que se encuentre tarde o temprano con la excepción InstantiationException. Hasta la versión 1.5, el api de Java indicaba respecto a esta excepción algo así como:

Lanzada cuando una aplicación intenta crear una instancia de una clase utilizando el método newInstance de la clase Class, pero el objeto no puede ser instanciado porque es una interfaz o una clase abstracta.

Este mensaje tenía la habilidad de hacernos pensar que los especificados eran los únicos motivos que podían hacer que se lanzase esta excepción. Pero entonces, si estamos absolutamente seguros de que estamos intentando instanciar una clase no abstracta, ¿por qué me puede aparecer el error?

Pues por ejemplo, porque estés ejecutando algo así:

Object o = Class.forName("Clase").newInstance();

Y en la clase Clase no tengas explícitamente definido el constructor sin parámetros. Simplemente añadiéndolo a la definición de la clase solucionaremos entonces el problema.

Es por esto que a partir de la versión 6, el api de la clase InstantiationException ha cambiado su descripción a:

Lanzada cuando una aplicación intenta crear una instancia de una clase utilizando el método newInstance de la clase Class, pero el objeto no puede ser instanciado. La creación de la instancia puede fallar por varios motivos, incluyendo, pero no limitándolos a:

  • El objeto representa a una clase abstracta, una interfaz, un array, un tipo primitivo o void.
  • La clase no tiene constructor sin argumentos.
Mucho mejor.

domingo, 5 de junio de 2011

Uso de CellFactory en Java FX 2

Tras las primeras horas bicheando JavaFX 2, aquí un post en el que explico cómo definir la forma en que se presentan los elementos de un lista.

Lo que tenemos es un objeto de tipo ListView, que se muestra por pantalla como una lista de elementos. Lo primero que debemos tener en cuenta, es que la forma más correcta de manejar su contenido es tener una ObservableList, que será sobre la que hagamos los cambios (adición, eliminación y actualización de elementos). Si fijamos esta lista observable como contenido de la ListView, ésta será notificada cada vez que se produzca un cambio en la colección, y tendremos la vista de nuestra aplicación siempre actualizada.



Pero lo que necesitamos en este caso es manejar una lista de elementos más complejos. Por ejemplo, supongamos que tenemos la clase Persona:


Sin problema podríamos crear una lista para presentar una serie de personas con el siguiente código.


Pero al ejecutar este código, lo que veríamos en la lista sería el valor obtenido al llamar al método toString de la clase Persona. Si no lo hemos sobrescrito, se mostraría la referencia al objeto. Un primer paso para refinar este comportamiento se reduciría a crear un método toString que devolviese el nombre y apellidos de la persona, y así podríamos ver esos valores en la lista.

Pero supongamos que queremos ir más allá, y no sólo presentar el nombre completo de la persona, sino también utilizar un color distinto en función de su edad, mostrando en rojo a los adultos, y en azul a los que todavía no lo son. Pues para eso podemos utilizar el método setCellFactory de la clase ListView.


Como podemos ver, la entrada al método es un objeto que implemente la interfaz Callback, con el que básicamente le decimos a la lista cómo debe crear sus celdas. La interfaz define un único método, call, que devolverá, en nuestro caso, una celda que contiene una persona (ListCell). 



Como podemos ver en el código anterior, el método call define en primer lugar un elemento Text, y después una ListCell, que es la celda que vamos a devolver. En este caso creamos una celda de Persona, y construimos el objeto sobrescribiendo el método updateItem, en el que configuramos el elemento Text como queremos, y lo asignamos como nodo de la celda. De esta forma, cuando veamos la lista por pantalla, lo que se presentará para cada elemento será el Text, con la configuración dada en función de los datos del objeto Persona correspondiente.

No sé si la explicación ha quedado clara, pero al ejecutarlo se verá que la idea es muy sencilla. Además, a partir de aquí surgen muchas posibilidades, ya que podemos representar elementos complejos dentro de una lista contando con todas las posibilidades de JavaFX.