Mostrando las entradas con la etiqueta capitulo 4. Mostrar todas las entradas
Mostrando las entradas con la etiqueta capitulo 4. Mostrar todas las entradas

4.6. Apagar una Aplicación

Un usuario puede cerrar la sesión o cerrar la página web o el navegador, por lo que una sesión y la instancia application asociada pueden terminarse. La finalización de una aplicación puede ser iniciada por la lógica de la aplicación. De lo contrario, será terminada automáticamente cuando la sesión del Servlet expire.

4.6.1 Cerrar una Aplicación

Si el usuario sale de la aplicación a través de la interfaz de usuario, un controlador de eventos debería llamar al método close() en la clase Application para cerrar la sesión.

En el siguiente ejemplo, tenemos un botón Salir, que termina la sesión del usuario.

Button botonCerrar = new Button("Salir");

botonCerrar.addListener(new Button.ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        getMainWindow().getApplication().close();
    } 
});
 
principal.addComponent(botonCerrar);

Notará que el cierre de la aplicación, simplemente recarga la aplicación con una nueva instancia de Application. Puede configurar la ventana para redirigir a una dirección URL diferente (que no recarga la aplicación) con setLogoutURL. En su clase application, escriba:

setLogoutURL("/salir.html");

4.6.2 Controlar el Cierre de una Ventana

El cierre de la ventana principal (o todas las ventanas de nivel de aplicación) no cierra la sesión y la instancia de la aplicación quedará colgando. Necesitará programar tal comportamiento controlando los eventos de cierre de las ventanas.

Si el usuario cierra una ventana del navegador, como la ventana principal o cualquier otra ventana de nivel de aplicación, la ventana enviará una petición final AJAX al servidor, el cual disparará un Window.CloseEvent para la ventana cerrada. Puede controlar el evento con un Window.CloseListener. En caso de que el usuario cierre el navegador, el evento es disparado para cada ventana abierta.

// Cerrar la aplicación si la ventana principal es cerrada.
principal.addListener(new Window.CloseListener(){
   @Override
    public void windowClose(CloseEvent e) {
       System.out.println("Cerrando la aplicación");
       getMainWindow().getApplication().close();
    } 
});

Tenga en cuenta que actualizar una ventana significa cerrarla y volverla a abrir. Por lo tanto, si tiene un controlador de cierre como el anterior, el usuario pierde la posibilidad de actualizar la ventana del navegador.

En el probable caso de que el navegador se bloquee, ningún evento de cierre es comunicado al servidor. Como el servidor no tiene manera de conocer acerca del problema, y la sesión quedará colgando hasta que expire el tiempo de espera de la sesión. Durante este tiempo, el usuario puede reiniciar el navegador, abrir el URL de la aplicación, y la ventana principal le mostrará donde el usuario le dejó. Esto puede ser un comportamiento deseado en muchos casos, pero a veces no lo es y puede crear un problema de seguridad.



Anterior
4.5. Referenciar Recursos
Siguiente
4.7. Controlar Errores

4.5. Referenciar Recursos

Las aplicaciones web trabajan sobre la web y tienen varios recursos, como imágenes o archivos descargables, que el navegador web tiene que obtener desde el servidor. Estos recursos son utilizados típicamente en los componentes de interfaz de usuario Embedded (imágenes) o Link (archivos descargables). Varios componentes, tales como TabSheet, también pueden incluir iconos, los cuales también son manejados como recursos.

Un servidor web puede manejar muchas de estas peticiones de recursos estáticos sin tener que pedirlas desde la aplicación, o desde el que el objeto Application puede proporcionarnos. Para los recursos dinámicos, la aplicación de usuario debe ser capaz de crearlos dinámicamente. Vaadin proporciona interfaces de petición de recursos para las aplicaciones de modo que puedan devolver los diversos tipos de recursos, tales como archivos o recursos creados dinámicamente. Esto incluye las clases StreamResource y URI y controladores de parámetros descritos en la Sección 12.5.1, "Controlador de URI" y la Sección 12.5.2, "Controlador de Parametros", respectivamente.

Vaadin proporciona también herramientas de bajo nivel para la recuperación del URI y otros parámetros de una petición HTTP. En primer lugar, examinaremos cómo las aplicaciones pueden ofrecer diversos tipos de recursos y luego buscar en interfaces de bajo nivel para el manejo de los URIs y parámetros para proporcionar los recursos y funcionalidades.

Observe que el uso del URI o controladores de parámetro para crear "páginas" no es significativo en Vaadin o en aplicaciones AJAX en general. Por favor, consulte la Sección 12.1, "Caracteristicas Especiales de Aplicaciones AJAX" para una explicación detallada.

4.5.1. Interfaz y Clases Resource

Vaadin tiene dos interfaces para los recursos: una interfaz genérica Resource y una interfaz ApplicationResource más específica para los recursos proporcionados por la aplicación.

Figura 4.4. Diagrama de la Interfaz y Clase Resource

Los recursos de ApplicationResource son manejados por la clase Application. Cuando usted crea tal recurso, le da el objeto application al constructor. El constructor registra el recurso en la aplicación usando el método addResource.

Application maneja peticiones de los recursos y permite acceder a los recursos utilizando un URI. El URI consiste en el nombre de la base de la aplicación y un nombre relativo del recurso. El nombre relativo es "APP/"+iddelrecurso+"/"+nombredelarchivo, por ejemplo "APP/1/miimagen.png". iddelrecurso es un identificador numérico generado para hacer recursos únicos, y nombredelarchivo es el nombre de fichero del recurso proporcionado en el constructor de su clase. Sin embargo, la aplicación que utiliza un recurso no suele tener en cuenta su URI. Sólo tiene que dar el recurso a un Embedded o Link apropiado o a algún otro componente de interfaz de usuario, que maneje el renderizado del URI.

4.5.2. Recursos de Archivos

Los recursos de archivos son archivos almacenados en cualquier parte del sistema de archivos. El uso de los recursos de archivo generalmente, se divide en dos categorías principales: los archivos descargados y las imágenes embebidas.

Un objeto file que puede ser accedido como un recurso de archivo es definido con la clase estándar java.io.File. Puede crear el archivo, ya sea con una ruta absoluta o con una relativa, pero la ruta base de la ruta de acceso relativa depende de la instalación del servidor web. Por ejemplo, en Apache Tomcat, el directorio actual por defecto es la ruta de instalación de Tomcat.

4.5.3. Recursos de Cargador de Clase

ClassResource permite que los recursos sean cargados desde el paquete desplegado de la aplicación utilizando el Cargador de Clase de Java. En el ejemplo de una línea más abajo, se carga un recurso de imagen desde el paquete de la aplicación y es mostrado en un componente Embedded.

ventanaPrincipal.addComponent(new Embedded ("",
        new ClassResource("sonriente.jpg",
                  ventanaPrincipal.getApplication())));

4.5.4. Recursos de Tema (Estilo)

Los recursos de tema de la clase ThemeResource son archivos, generalmente imagenes, incluidas en un tema. Un tema es localizado en la ruta camino VAADIN/themes/nombredeltema en una aplicación web. El nombre de un recurso de tema es proporcionado como parámetro para el constructor, con una ruta relativa a la carpeta themes.

// Un recurso de tema en el actual tema ("book-examples")
// Localizado en: VAADIN/themes/book-examples/img/themeimage.png
ThemeResource recurso = new ThemeResource("img/themeimage.png");
 
// utilizar el recurso
Embedded imagen = new Embedded("Mi Imagen del Tema", recurso);

El resultado se muestra en la Figura 4.5, "Recursos de Tema", ilustra también la estructura de la carpeta para el archivo de recursos del tema en un proyecto de Eclipse.

Figura 4.5. Recursos de Tema

Para utilizar recursos de tema, debe establecer el tema para la aplicacion. Consulte el Capítulo 8, Temas para mayor informacion sobre los temas.

4.5.5. Recursos de Flujo

Los recursos de flujo son recursos de aplicaciones que permiten la creación de contenido dinámico de recursos. Los gráficos son ejemplos típicos de imágenes dinámicas. Para definir un recurso de flujo, es necesario implementar la interfaz StreamResource.StreamSource y su método getStream. El método debe devolver un InputStream desde el cual el flujo pueda ser leído.

El siguiente ejemplo muestra la creación de una simple imagen en formato de imagen PNG.

import java.awt.image.*;

public class MiFuenteImagen
             implements StreamResource.StreamSource {
    ByteArrayOutputStream bufferImagen = null;
    int recargas = 0;
    
    /* Necesitamos implementar este método que devuelve
     * el recurso como un flujo. */
    public InputStream getStream () {
        /* Crear una imagenn y dibujar algo en ella. */
        BufferedImage imagen = new BufferedImage (200, 200,
                               BufferedImage.TYPE_INT_RGB);
        Graphics dibujable = imagen.getGraphics();
        dibujable.setColor(Color.lightGray);
        dibujable.fillRect(0,0,200,200);
        dibujable.setColor(Color.yellow);
        dibujable.fillOval(25,25,150,150);
        dibujable.setColor(Color.blue);
        dibujable.drawRect(0,0,199,199);
        dibujable.setColor(Color.black);
        dibujable.drawString("Recargas = " + recargas, 75, 100);
        recargas++;

        try {
            /* Escriba la imagen en un búfer. */
            bufferImagen = new ByteArrayOutputStream();
            ImageIO.write(imagen, "png", bufferImagen);
            
            /* Devolver un flujo desde el buffer. */
            return new ByteArrayInputStream(
                         bufferImagen.toByteArray());
        } catch (IOException e) {
            return null;
        }
    }
}

El contenido de la imagen generada es dinámico, ya que actualiza el contador recargas en cada llamada. El método ImageIO escribe la imagen para un flujo de salida, mientras, tuvimos que devolver un flujo de entrada, por lo que almacenamos los contenidos de la imagen en un búfer temporal.

Puede utilizar los recursos de varias maneras. Algunos componentes de interfaz de usuario, como Link y Embedded, toman sus parámetros como un recurso.

A continuación se mostrará la imagen con el componente Embedded. El constructor StreamResource obtiene una referencia de la aplicación y se registra en los recursos de la aplicación. Supongamos que principal es una referencia a la ventana principal y this es el objeto application.

// Crear una instancia de nuestra fuente de flujo.
StreamResource.StreamSource fuenteImagen = new MiFuenteImagen();
 
// Crear un recurso que utiliza el origen de flujo y proporcinarle un nombre.
// El constructor registrará automáticamente el recurso en
// la aplicación.
StreamResource recursoImagen =
        new StreamResource(fuenteImagen, "miImagen.png", this);
 
// Crear un componente integrado que recibe su contenido
// del recurso.
principal.addComponent(new Embedded("Titulo de la imagen", recursoImagen));

La imagen se verá de la siguiente manera:

Figura 4.6. Pantallazo del ejemplo de recurso de flujo con una imagen embebida

Hemos llamado a este recurso como miImagen.png. La aplicación agrega una llave de recurso al nombre de archivo del recurso para hacerlo único. El URI completo será como http://localhost:8080/bancodepruebas/APP/1/miImagen.png. El APP/1/miImagen.png al final es la parte relativa del URI. Puede obtener la parte relativa de los recursos del URI desde la aplicación con Application.getRelativeLocation().

Otra solución para crear contenido dinámico es un controlador del URI, posiblemente junto con un controlador de parámetro. Vea la Sección 12.5.1, "Controlador de URI" y la Sección 12.5.2, "Controlador de Parametros".



Anterior
4.4. Controlar Eventos con Oyentes
Siguiente
4.6. Apagar una Aplicación

4.4. Controlar Eventos con Oyentes

Vamos a poner en práctica lo que aprendimos del manejo de eventos en la Sección 3.5, "Eventos y Oyentes". Puede manejar los eventos de tres formas básicas, como se muestra a continuación.

El siguiente ejemplo sigue un modelo típico en el que tiene un componente Button y un oyente que se encarga de la interacción del usuario (clics) comunicado a la aplicación por eventos. Aquí definimos una clase que escucha los eventos clic.

public class ElBoton implements Button.ClickListener {
    Button elBoton;

    /** Crear el botón en el contenedor proporcionado. */
    public ElBoton(AbstractComponentContainer contenedor) {
        elBoton = new Button ("No presione este botón");
        elBoton.addListener(this);
        contenedor.addComponent(elBoton);
    }
    
    /** Controlar los eventos clic del boton para el boton. */
    public void buttonClick (Button.ClickEvent event) {
        elBoton.setCaption ("No presione este botón de nuevo");
    }
}

Como una aplicación suele recibir eventos de varios componentes de la misma clase, tales como múltiples botones, esta tiene que ser capaz de distinguir entre los componentes individuales. Hay varias técnicas para hacer esto, pero probablemente la más fácil es utilizar la propiedad del evento recibido, que se establece en el objeto enviando el evento. Esto requiere tener a mano una referencia para cada objeto que emite los eventos.

public class ElBoton implements Button.ClickListener {
    Button elBoton;
    Button segundoBoton;

    /** Crear dos botones en el contenedor proporcionado. */
    public ElBoton(AbstractComponentContainer contenedor) {
        elBoton = new Button ("No presione este botón");
        elBoton.addListener(this);
        contenedor.addComponent(elBoton);
        
        segundoBoton = new Button ("Yo soy un botón también");
        segundoBoton.addListener(this);
        contenedor.addComponent (segundoBoton);
    }
    
    /** Controlar los eventos clic del boton para los dos boton. */
    public void buttonClick (Button.ClickEvent event) {
        if (event.getButton() == elBoton)
            elBoton.setCaption("No presione este botón de nuevo");
        else if (event.getButton() == segundoBoton)
            segundoBoton.setCaption("Yo no soy un número");
    }
}

Otra solución para manejar eventos múltiples de la misma clase implica vincular un origen de eventos a un método oyente en lugar de la clase. Un evento puede ser vinculado a un método utilizando otra versión del método addListener(), el cual toma el método que maneja el evento como un parámetro. El método puede ser pasado ya sea por el nombre del método o como un objeto Method. En el siguiente ejemplo, utilizamos el nombre del método como una cadena (el cual no es comprobado en tiempo de compilación).

public class ElBoton2 implements Button.ClickListener {
    Button elBoton;
    Button segundoBoton;

    /** Crear dos botones en el contenedor proporcionado. */
    public ElBoton2(AbstractComponentContainer contenedor) {
        elBoton = new Button ("No presione este botón");
        elBoton.addListener(Button.ClickEvent.class, this,
                              "elButtonClick");
        contenedor.addComponent(elBoton);
        
        segundoBoton = new Button ("Yo soy un botón también");
        segundoBoton.addListener(Button.ClickEvent.class, this,
                                 "segundoButtonClick");
        contenedor.addComponent (segundoBoton);
    }
    
    public void elButtonClick (Button.ClickEvent event) {
        elBoton.setCaption ("No presione este botón de nuevo");
    }

    public void segundoButtonClick (Button.ClickEvent event) {
        segundoBoton.setCaption("Yo no soy un número");
    }
}

Agregar un método oyente con addListener() es realmente sólo un wrapper que crea un objeto oyente com.vaadin.event.ListenerMethod, que es un adaptador desde una clase oyente a un método. Este implementa la interfaz java.util.EventListener y por lo tanto puede trabajar para cualquier origen de eventos utilizando la interfaz. Tenga en cuenta que no todas las clases oyentes necesariamente heredan la interfaz EventListener.

La tercera forma, que utiliza definiciones de clases locales anónimas, es a menudo la más fácil ya que no necesita obstaculizar la administración de la clase con nuevas interfaces o métodos. En el siguiente ejemplo se define una clase anónima que hereda la interfaz Button.ClickListener e implementa el método buttonClick().

public class ElBoton3 {
    Button elBoton;
    Button segundoBoton;

    /** Crear dos botones en el contenedor proporcionado. */
    public ElBoton3(AbstractComponentContainer contenedor) {
        elBoton = new Button ("No presione este botón");

        /* Define un oyente en una clase anonima. */
        elBoton.addListener(new Button.ClickListener() {
            /* Controlar el clic. */
            public void buttonClick(ClickEvent event) {
                elBoton.setCaption (
                        "No presione este botón de nuevo");
            }
        });
        contenedor.addComponent(elBoton);
        
        segundoBoton = new Button ("Yo soy un botón también");
        segundoBoton.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                segundoBoton.setCaption ("Yo no soy un número!");            
            }
        });
        contenedor.addComponent (segundoBoton);
    }
}

También existen otras técnicas para la separación entre las diferentes fuentes. Ellas incluyen el uso de las propiedades de los objetos, nombres o títulos para separarlos entre ellos. Utilizar títulos o cualquier otro texto visible es generalmente desalentador, ya que puede crear problemas para la internacionalización. Utilizar otras cadenas simbólicas también puede ser peligroso, porque la sintaxis de estas cadenas se verifican sólo en tiempo de ejecución.

Los eventos son generalmente emitidos por el framework, pero también las aplicaciones pueden necesitar emitirlos en algunas situaciones, como cuando se requiere actualizar alguna parte de la interface de usuario. Los eventos pueden emitirse utilizando el método fireEvent(Component.Event) de AbstractComponent. El evento entonces es retransmitido a todos los oyentes del evento en particular de la clase para el objeto. Algunos componentes tienen un tipo de evento por defecto, por ejemplo, un Button tiene una clase Button.ClickEvent anidada y una correspondiente interfaz Button.ClickListener. Estos eventos pueden ser desencadenados con fireComponentEvent().



Anterior
4.3. Ventanas Secundarias
Siguiente
4.5. Referenciar Recursos

4.3. Ventanas Secundarias

Una ventana de nivel de aplicación puede tener varias ventanas secundarias flotantes. Están son manejadas por JavaScript del lado del cliente en tiempo de ejecución con características HTML utilizando Vaadin. Vaadin permite abrir y cerrar ventanas secundarias, refrescar una ventana desde otra, cambiar el tamaño de las ventanas, y desplazar el contenido de la ventana. Las ventanas secundarias normalmente son utilizadas por Ventanas de Diálogo y aplicaciones de Interfaz de Múltiples Documentos. Las ventanas secundarias son por defecto no modales; puede establecerlas a modales como se describe en la Sección 4.3.4, "Ventanas Modales".

Al igual que con todos los componentes de interfaz de usuario, la apariencia de una ventana y sus contenidos son definidos con los temas.

El control del usuario a una ventana secundaria está limitada a mover, redimensionar y cerrar la ventana. Maximizar o minimizar aún no están soportados.

4.3.1. Abrir y Cerrar Ventanas Secundarias

Puede abrir una ventana nueva creando un nuevo objeto Window y agregarlo a la ventana principal con el método addWindow() de la clase Application.

miVentana = new Window("Mi Ventana");
ventanaPrincipal.addWindow(miVentana);


Cierre la ventana de una manera similar, llamando a removeWindow() de la clase Application.

miAplicacion.removeWindow (miVentana);


El usuario puede, por defecto, cerrar una ventana secundaria haciendo clic en el botón de cierre en la esquina superior derecha de la ventana. Puede desactivar el botón estableciendo la ventana como de sólo lectura con setReadOnly(true). Tenga en cuenta que también puede deshabilitar el botón haciéndolo invisible en CSS con el formato "display: none". El problema con esta deshabilitación estética es que un usuario malintencionado podría volver a habilitar el botón y cerrar la ventana, lo que podría causar problemas y, posiblemente, ser un agujero de seguridad. Configurando la ventana como de sólo lectura no sólo desactiva el botón de cierre del lado del cliente, sino que también impide procesar el evento cerrar del lado del servidor.

El siguiente ejemplo demuestra el uso de una ventana secundaria en una aplicación. El ejemplo maneja la ventana con un componente personalizado que contiene un botón para abrir y cerrar la ventana.

/** El componente contiene un botón que permite abrir una ventana. */
public class AbridorVentana extends CustomComponent
                          implements Window.CloseListener {
    Window ventanaPrincipal;  // Referencia a la ventana principal
    Window miVentana;    // La ventana que se abrirá
    Button botonAbrir;  // El botón para abrir la ventana
    Button botonCerrar; // Un botón en la ventana
    Label  explicacion; // Un texto descriptivo

    public AbridorVentana(String label, Window principal) {
        ventanaPrincipal = principal;

        // El componente contiene un botón que abre la ventana.
        final VerticalLayout disenio = new VerticalLayout();
        
        botonAbrir = new Button("Abrir Ventana", this,
                                "abrirButtonClick");
        explicacion = new Label("Explicación");
        disenio.addComponent(botonAbrir);
        disenio.addComponent(explicacion);
        
        setCompositionRoot(disenio);
    }

    /** Controlar los clics de los dos botones. */
    public void abrirButtonClick(Button.ClickEvent event) {
        /* Crear una nueva ventana. */
        miVentana = new Window("Mi Cuadro de Diálogo");
        miVentana.setPositionX(200);
        miVentana.setPositionY(100);

        /* Agregar la ventana dentro de la ventana principal. */
        ventanaPrincipal.addWindow(miVentana);

        /* Escuchar los eventos 'cerrar' para la ventana. */
        miVentana.addListener(this);

        /* Agregar los componentes en la ventana. */
        miVentana.addComponent(
                new Label("Una etiqueta de texto en la ventana."));
        botonCerrar = new Button("Cerrar", this, "cerrarButtonClick");
        miVentana.addComponent(botonCerrar);

        /* Permitir abrir sólo una ventana a la vez. */
        botonAbrir.setEnabled(false);

        explicacion.setValue("Ventana abierta");
    }

    /** Controlar el clic del botón botonCerrar y cierre de la ventana. */
    public void cerrarButtonClick(Button.ClickEvent event) {
        /* Las ventanas son manejadas por el objeto application. */
        ventanaPrincipal.removeWindow(miVentana);

        /* Volver al estado inicial. */
        botonAbrir.setEnabled(true);

        explicacion.setValue("Cerrado con el botón");
    }

    /** En caso de que la ventana sea cerrada de otro modo. */
    public void windowClose(CloseEvent e) {
        /* Volver al estado inicial. */
        botonAbrir.setEnabled(true);

        explicacion.setValue("Cerrado con controles de la ventana");
    }
}

El ejemplo implementa un componente personalizado que hereda la clase CustomComponent. Este consiste de un Button que se utiliza para abrir una ventana y un Label para describir el estado de la ventana. Cuando la ventana es abierta, el botón es deshabilitado. Cuando la ventana es cerrada, el botón es habilitado de nuevo.

Puede utilizar el componente personalizado de arriba en la clase application con:

 public void init() { 
    Window principal = new Window("La Ventana Principal"); 
    setMainWindow(principal);

    principal.addComponent(new AbridorVentana("Abridor de Ventana", principal));
}

Cuando se agrega a una aplicación, la pantalla se verá cómo se ilustra en el siguiente pantallazo:

Figura 4.2. Abriendo una Ventana Secundaria

4.3.2. Posicionar una Ventana

Cuando es creada, una ventana tendrá un tamaño y una posición predeterminada. Puede especificar el tamaño de una ventana con los métodos setHeight() y setWidth(). Puede establecer la posición de la ventana con los métodos setPositionX() y setPositionY().

/* Crear una ventana nueva. */
miVentana = new Window("Mi Cuadro de Dialogo");
 
/* Establecer el tamaño de la ventana. */
miVentana.setHeight("200px");
miVentana.setWidth("400px");
 
/* Establecer la posición de la ventana. */
miVentana.setPositionX(200);
miVentana.setPositionY(50);

Tenga en cuenta que el tamaño de la ventana principal es desconocido y los métodos getHeight y getWidth devolverán -1.

4.3.3. Desplazamiento del Contenido en Ventanas Secundarias

Si una ventana secundaria tiene un tamaño fijo o porcentual y su contenido es demasiado grande para ajustarse al área del contenido, una barra de desplazamiento aparecerá para la dirección en particular. Por otro lado, si la ventana secundaria tiene un tamaño indefinido en la dirección, este se ajustará al tamaño del contenido y nunca obtener una barra de desplazamiento. Las barras de desplazamiento en las ventanas secundarias regulares son manejadas con características HTML, es decir, la propiedad overflow: auto en CSS.

Como Window extiende a Panel, las ventanas también son Scrollable. Tenga en cuenta que la interfaz define un desplazamiento programático, no un desplazamiento por el usuario. Por favor, consulte la Sección 6.6, "Panel".

4.3.4. Ventanas Modales

Una ventana modal es una ventana secundaria que tiene que ser cerrada por el usuario antes de poder continuar para usar la ventana padre. Las ventanas de cuadro de diálogo son generalmente modales. La ventaja de las ventanas modales es la simplificación de la interacción del usuario, que puede contribuir a la claridad de la interfaz de usuario. Las ventanas modales también son fáciles de utilizar desde una perspectiva de desarrollo, porque, la interacción del usuario es aislada para ellos, los cambios en el estado de la aplicación son más limitados, mientras que la ventana modal esté abierta. La desventaja de las ventanas modales es que pueden restringir demasiado el flujo de trabajo.

Figura 4.3. Pantallazo de la Aplicación Demostracion Ventana Modal

Dependiendo de la configuración del tema, la ventana padre puede ser atenuada, mientras la ventana modal esté abierta.

La aplicación demo de Vaadin incluye un ejemplo del uso de ventanas modales. La Figura 4.3, "Pantallazo de la Aplicación Demostracion Ventana Modal" arriba es de la aplicación demo. El ejemplo incluye el código fuente.

Advertencia de Seguridad
La modalidad de las ventanas secundarias es meramente una característica del lado del cliente y puede ser burlado con el ataque por código del lado del cliente. No debe confiar en la modalidad de las ventanas secundarias en situaciones críticas de seguridad tales como las ventanas de inicio de sesión.



Anterior
4.2. Administrar la Ventana Principal
Siguiente
4.4. Controlar Eventos con Oyentes

4.2 Administrar la Ventana Principal

Como se explicó en la Sección 12.1, "Caracteristicas Especiales de Aplicaciones AJAX", una aplicación web de AJAX por lo general se ejecuta en una sola "página web" en una ventana del navegador. Generalmente la página no es recargada después de que es abierta al principio, pero comunica la interacción del usuario con el servidor a través de comunicaciones AJAX. Una ventana en una aplicación AJAX es por lo tanto más como una ventana en una aplicación de escritorio y menos como una página web.

Window es el contenedor de nivel superior de una interfaz de usuario mostrado en una ventana de navegador. Cuando una aplicación AJAX normalmente se ejecuta en una sola "página" (URL), por lo general hay una sola ventana, la ventana principal. Se puede acceder a la ventana principal utilizando la dirección URL de la aplicación. Establezca la ventana principal con el método setMainWindow() de la clase Application.

import com.vaadin.ui.*;

public class HolaMundo extends com.vaadin.Application {
    public void init() { 
        Window principal = new Window("La Ventana Principal"); 
        setMainWindow(principal);

        ... llene la ventana principal con componentes ...     }
}

Puede agregar componentes a la ventana principal, o a cualquier otra ventana, con el método addComponent(), que en realidad añade el componente al componente de diseño raíz vinculado a la ventana. Si desea utilizar otro diseño raíz por defecto, puede establecerlo con setContent(), como se explica en la Sección 6.2, "Diseño Raiz Window y Panel".

Vaadin tiene dos tipos básicos de ventana: las ventanas de nivel de aplicación, tales como la ventana principal y las ventanas secundarias (o sub-ventanas) dentro de las ventanas de nivel de aplicación. Las ventanas secundarias se explican en la siguiente sección, mientras que las ventanas de nivel de aplicación se tratan en la Sección 12.2, "Ventanas de Nivel de Aplicación".



Anterior
Capítulo 4. Escribir una Aplicación Web
Siguiente
4.3. Ventanas Secundarias

Capítulo 4. Escribir una Aplicación Web

Este capítulo proporciona los fundamentos del desarrollo de aplicaciones web con Vaadin, concentrándose en los elementos básicos de una aplicación desde un punto de vista práctico.

Si eres un principiante en el desarrollo con AJAX, puede beneficiarse de la Sección 12.1, "Caracteristicas Especiales de Aplicaciones AJAX". En él se explica el rol de las páginas en aplicaciones web AJAX, y proporciona algunos modelos de diseño básico para las aplicaciones.

4.1. Información General

Una aplicación hecha con Vaadin se ejecuta como un Servlet Java en un contenedor de Servlets. El punto de entrada es la clase application, que necesita crear y administrar todos los componentes de la interfaz de usuario necesarios, incluyendo las ventanas. La interacción del usuario es manejada con oyentes de eventos, simplificado directamente por las vinculaciones de los componentes de interfaz de usuario a los datos. El aspecto visual es definido en temas como archivos CSS. Los iconos, otras imágenes, y archivos descargables son manejados como recursos, que pueden ser externos o servidos por el servidor de aplicaciones o por la propia aplicación.

Figura 4.1. Arquitectura de una Aplicación

La Figura 4.1, "Arquitectura de una Aplicación" arriba es la arquitectura básica de una aplicación hecha con el framework Vaadin, con todos los elementos principales, que se presentan a continuación y discutidos en detalle en este capítulo.

Primero que todo, una aplicación que utiliza Vaadin debe definir una clase application que hereda la clase abstracta com.vaadin.Application. La clase application debe implementar el método init().

public class MiApp extends com.vaadin.Application {

    public void init() { 
        ... el código de inicialización va aquí ...
    }
}

Además de actuar como el punto de entrada en el servlet, la clase Application proporciona facilidades para acceder a la ventana, el control de ejecución y la selección de temas. La API de application puede parecer similar a la API de Java Servlet, pero sólo es superficial. El framework Vaadin asocia las peticiones con sesiones, de modo que una instancia de la clase application es realmente un objeto de sesión. Debido a esto, puede desarrollar aplicaciones web, como lo haría con el desarrollo de aplicaciones de escritorio.

Reiniciar la Sesión de la Aplicación

Cuando abre la dirección URL de la aplicación, se crea una nueva sesión de usuario. La sesión se conserva incluso si vuelve a cargar la página. Sin embargo, ya que a Eclipse le gusta hacer el despliegue en caliente para Tomcat, y a Tomcat le gusta persistir sesiones en el cierre del servidor, usted puede experimentar un problema y es que la aplicación no vuelve a su estado inicial después de modificar el código o incluso reiniciar el servidor.

Añadiendo el parámetro ?restartApplication en la URL le indica al servlet Vaadin que cree una nueva instancia de Application cuando se recarge la página.

Lo más importante en la inicialización, es la creación de la ventana principal (véase más adelante), que cualquier aplicación tiene. Esto, y el despliegue de la aplicación como un Servlet Java en el contenedor de Servlets, tal como se describe en la Sección 4.8, "Configurar el Entorno de la Aplicación", son los requisitos mínimos para una aplicación.

A continuación se muestra una breve descripción de los elementos básicos de una aplicación:

Ventanas
Una aplicación siempre tiene una ventana principal, tal como se describe en la Sección 4.2, "Administrar la Ventana Principal". Una aplicación puede realmente tener varias ventanas de nivel de aplicación, todas unidas a la misma sesión de la aplicación, como se describe en la Sección 12.2, "Ventanas de Nivel de Aplicación". Las ventanas de nivel de aplicación pueden contener sub-ventanas no nativas, que son esencialmente los componentes de diseño flotante manejados dentro del navegador.

Componentes de Interfaz de Usuario
La interfaz de usuario se compone de los componentes de interfaz de usuario (UI) que son creados y presentados por la aplicación. La interacción del usuario con los componentes causa eventos (véase abajo) relacionados con el componente que la aplicación debe manejar. La mayor parte de los componentes están vinculados a algun dato utilizando el Modelo de Datos (véase abajo). Puede hacer sus propios componentes de interfaz de usuario ya sea a través de herencia o composición. Para una referencia completa de los componentes de interfaz de usuario, véase el Capítulo 5, Componentes de Interfaz de Usuario, para los componentes de diseño, vea el Capítulo 6, Admnistrar el Diseño, y para la composición de componentes, consulte la Sección 5.23 "Composición de Componentes con CustomComponent".

Eventos y Oyentes
Los eventos y oyentes que manejan los eventos, son la base del manejo de la interacción del usuario en una aplicación. La Sección 3.5, "Eventos y Oyentes" aportó una introducción a los eventos y oyentes desde un punto de vista arquitectónico, mientras que la Sección 4.4, "Controlar Eventos con Oyentes", más adelante este capítulo tiene una visión más práctica.

Recursos
Una interfaz de usuario puede mostrar imágenes o enlaces a páginas web o documentos descargables. Estos son recursos, que pueden ser externos o proporcionados por el servidor web o la propia aplicación. La Sección 4.5, "Referencias Recursos" proporciona una visión práctica de los diferentes tipos de recursos.

Temas (Estilos)
La presentación y la lógica de la interfaz de usuario están separadas. Mientras que la lógica de la interfaz de usuario es controlada como código de Java, la presentación es definida en temas como CSS. Vaadin proporciona un tema predeterminado. Los temas definidos por el usuario pueden, ademas de las hojas de estilo, incluir plantillas HTML que definen diseños personalizados y otros recursos temáticos, tales como imágenes. Los temas son discutidos en detalle en el Capítulo 8, Temas, los diseños personalizados en la Sección 6.13, "Diseños Personalizados", y los recursos de temas en la Sección 4.5.4, "Recursos de Temas".

Vincular Datos
Los campos de los componentes son esencialmente vistas a datos, representados en un modelo de datos. Utilizando el modelo de datos, los componentes pueden actualizar los datos de la aplicación directamente, sin la necesidad de ningún código de control. Un modelo de componentes de un campo siempre está vinculado a una propiedad, un elemento, o un contenedor, dependiendo del tipo de campo. Si bien todos los componentes tienen un modelo de datos por defecto, que pueden vincularse a un origen de datos definido por el usuario. Por ejemplo, puede vincular un componente table a la respuesta de una consulta SQL. Para una descripción completa de vinculación de datos en Vaadin, por favor, consulte el Capítulo 9, "Vincular Componentes a Datos".



Anterior
3.5. Eventos y Oyentes
Siguiente
4.2. Administrar la Ventana Principal