## Cómo Utilizar la Clase JProgressBar

Una tarea ejecutándose en un programa puede tardar un poco en completarse. Un programa amigable proporciona alguna indicación al usuario sobre lo que puede tardar la tarea y lo que ya lleva realizado.

El paquete Swing proporciona tres clases para ayudar a crear GUIs que monitoricen y muestren el progreso de tareas de larga duración:

JProgressBar
  Una barra de progreso que muestra gráficamente qué cantitad total de la tarea se ha terminado. Puedes ver Cómo usar Progress Bars para más información.
ProgressMonitor
  Un ejemplar de esta clase monitoriza el progreso de una tarea. Si el tiempo enlapsado de la tarea excede un valor especificado en el programa, el monitor trae un diálogo con una descripción de la tarea, una nota de estado, una barra de progreso, un botón Ok, y un botón Cancel. Puedes ver Cómo usar Progress Monitors para más detalles.
ProgressMonitorInputStream
  Un stream de entrada con un monitor de progreso añadido, que monitoriza la lectura desde el stream. Se utiliza un ejemplar de este stream como cualquier otro stream. Se puede obtener el monitor de progreso del stream llamando a getProgressMonitor y configurándolo como se describe en Cómo usar Progress Monitors.

Después de ver una barra de progreso y un monitor de progreso en acción, Decidir si utilizar una Barra o un Monitor de Progreso puede ayudarnos a decidir cuál es el apropiado para nuestra aplicación.

#### Cómo usar Progress Bars

> Aquí podemos ver una imagen de una pequeña aplicación que utiliza una barra de progreso para medir el progreso de una tarea que se ejecuta:

> > Intenta esto:
> > 1. Compila y ejecuta la aplicación. El fichero fuente es ProgressBarDemo.java. También necesitarás LongTask.java y SwingWorker.java.
> > 2. Pulsa el botón Start. Mira la barra de progreso mientras la tarea progresa. La tarea muestra su salida en el área de texto en la parte inferior de la ventana.

> Abajo está el código de ProgressBarDemo.java que crea y configura la barra de proceso:

>     ...where member variables are delcared...
>     JProgressBar progressBar;
>     ...
>         ...in the constructor for the demo's frame...
>         progressBar = new JProgressBar(0, task.getLengthOfTask());
>         progressBar.setValue(0);
>         progressBar.setStringPainted(true);

> El constructor usado para crear la barra de progreso selecciona los valores máximo y mínimo de la barra. También se pueden seleccionar estos valores con los métodos setMinimum y setMaximum. Los valores mínimo y máximo utilizados en este programa son 0 y la longitud de la tarea, lo que es típico de muchos programas y tareas. Sin embarguo, los valores máximo y mínimo de una barra de progreso pueden ser cualquier valor, incluso negativos. El código también selecciona el valor actual de la barra a 0. Los valores mínimo, actual, y máximo deben relacionarse de esta forma:

>     minimum <= current <= maximum

> Si se intenta seleccionar uno de los valores y el nuevo valor viola la relación, la barra de progreso ajusta uno o más de los otros valores de acuerdo a las reglas establecidas por BoundedRangeModel para mantener la relación.

> La llamada a setStringPainted hace que la barra de progreso muestre un string de porcentaje dentro de sus límites. Por defecto, la cadena indica el porcentaje completo de la barra de progreso. El string de procentaje es el valor devuelto por el método getPercentComplete formateado a porcentaje. Otra alternativa es mostrar un string diferente con setString.

> Se arranca la tarea pulsando el botón Start. Una vez que la tarea ha comenzado, un temporizador (un ejemplar de la clase Timer) dispara un evento actión cada segundo. Aquí está el método ActionPerformed del oyente de ation del temporizador:

>     public void actionPerformed(ActionEvent evt) {
>         progressBar.setValue(task.getCurrent());
>         taskOutput.append(task.getMessage() + newline);
>         taskOutput.setCaretPosition(taskOutput.getDocument().getLength());
>         if (task.done()) {
>     	Toolkit.getDefaultToolkit().beep();
>     	timer.stop();
>     	startButton.setEnabled(true);
>     	progressBar.setValue(progressBar.getMinimum());
>         }
>     }

La línea en negrita obtiene la cantidad de trabajo completada por la tarea y actualiza la barra de progreso con ese valor. Por eso la barra de progreso mide el progreso hecho por la tarea cada segundo, no el tiempo enlapsado. El resto del código actualiza la salida, y si la tarea se ha completado, desactiva el temporizador, y resetea los otros controles.

Como se ha mencionado antes, la tarea de larga duración de este programa se ejecuta en un thread separado. Generalmente, es una buena idea aislar una tarea potencialmente de larga duración en su propio thread para que no bloquee el resto del programa. La tarea de larga duración está implementada por LongTask.java, que utiliza un SwingWorker para asegurarse de que el thread se ejecuta de forma segura dentro de un programa Swing. Puedes ver Usar la clase SwingWorker en Threads y Swing para más información sobre la clase SwingWorker.

#### Cómo usar Progress Monitors

> Ahora, reescribamos el ejemplo anterior para utilizar un monitor de progreso en vez de una barra de progreso. Aquí tenemos una imagen del nuevo programa, ProgressMonitorDemo.java:

> La operación general de este programa es similar al anterior. Se pulsa el botón Start para arrancar la misma tarea de larga duración utilizada en el programa anterior. La tarea muestra la salida en el área de texto de la parte inferior de la ventana. Sin embargo, este programa utiliza un monitor de progreso en vez de una barra de progreso.

> El ejemplo anterior creaba la barra de progreso al arrancar. En contraste, este programa crea el monitor en el método actionPerformed del oyente de action del botón Start. Un monitor de progreso no puede utilizarse más de una vez, por eso se debe crear uno nuevo cada vez que se arranca una nueva tarea.

> Aquí está la sentencia que crea el monitor de progreso:

>     progressMonitor = new ProgressMonitor(ProgressMonitorDemo.this,
>                                           "Running a Long Task",
>                                           "", 0, task.getLengthOfTask());

> El constructor utilizado en este ejemplo inicializa varios parámetros del monitor de progreso.
> - El primer argumento proporciona el componente padre del diálogo desplegado para el monitor de progreso.
> - El segundo argumento es un String que describe la naturaleza de la tarea a monitorizar. Este string se mostrará en el diálogo.
> - El tercer argumento es otro String que proporciona una nota de estado cambiable. El ejemplo utiliza una cadena vacía porque la nota es actualizada periódicamente cuando la tarea se ejecuta. Si proporcionamos null para este argumento, la nota se omite del diálogo. El ejemplo actualiza la nota mientras la tarea se esta ejecutando cada vez que el temporizador dispara un evento action (actualiza el valor actual del monitor al mismo tiempo):

>       progressMonitor.setNote(task.getMessage());
>       progressMonitor.setProgress(task.getCurrent());

> - Los últimos dos argumentos proporcionan los valores mínimo y máximo, respectivamente, para la barra de progreso mostrada en el diálogo.
> Después el ejemplo crea el monitor de progreso, y lo configura:

>     progressMonitor.setProgress(0);
>     progressMonitor.setMillisToDecideToPopup(2 * ONE_SECOND);

> La primera línea selecciona la posición actual de la barra de progreso del diálogo. La segunda indica que el monitor debería desplegar un diálogo si la tarea se ejecuta durante más de dos segundos.

> Por el simple echo de que este ejemplo utiliza un monitor de progreso, añade una característica que no estaba presente en la versión del programa que utiliza una barra de progreso. El usuario puede cancelar la tarea pulsando el botón Cancel del diálogo. Aquí tenemos el código del ejemplo que chequea si el usuario cancela la tarea o si la tarea sale normalmente:

>     if (progressMonitor.isCanceled() || task.done()) {
>         progressMonitor.close();
>         task.stop();
>         Toolkit.getDefaultToolkit().beep();
>         timer.stop();
>         startButton.setEnabled(true);
>     }

> Observa que el monitor de progreso no cancela por si mismo la tarea. Proporciona el GUI y el API para permitir que el programa lo haga facilmente.

#### Decidir si utilizar una Barra o un Monitor de Progreso

> Se utiliza una barra de progreso si:
> - Queremos más control sobre la configuración de la barra de progreso. Si estamos trabajando directamente con una barra de progreso, podemos hacer que se muestre verticalmente, podemos proporcionar una cadena para que la muestre, podemos registrar oyentes de cambio, y podemos proporcionarle un modelo de datos personalizado.
> - Necesitamos mostrar otros controles o elementos GUI junto con la barra de progreso.
> - Necesitamos más de una barra de progreso. Con algunas tareas, necesitamos monitorizar más de un parámetro. Por ejemplo, un programa de instalación podría monitoriazar el espacio de disco utilizado además del número de ficheros que ya han sido instalados.
> - Necesitamos reutilizar la barra de progreso. Una barra de progreso puede ser re-utilizada; un monitor de progreso no. El monitor de progreso no tiene un método reset, y una vez que millisToDecideToPopup ha expirado el monitor ha terminado su trabajo.

> Se utiliza un monitor de progreso si:

> - Si queremos mostrar fácilmente el progreso en un diálogo.
> - La tarea a ejecutar es secundaria y el usuario podría no estar interesado en el progreso de la tarea. El monitor de progreso proporciona al usuario una forma para hacer desaparecer el diálogo mientras la tarea se ejecuta.
> - Nuestra tarea es cancelable. El monitor de progreso proporciona al usuario una forma de cancelar la tarea. Todo lo que tenemos que hacer es llamar al método isCanceled del monitor de progreso para ver si el usuario ha pulsado el botón Cancel.
> - Nuestra tarea muestra un mensaje corto periódicamente mientras se ejecuta. El diálogo del monitor de progreso proporciona el método setNote para que la tarea pueda proporcionar mayor información sobre lo que está haciendo. Por ejemplo, una tarea de instalación podría informar del nombre de cada fichero instalado.
> - La tarea podría no tardar mucho tiempo en completarse. Decidimos en que punto una tarea tarda el tiempo suficiente para permitir que el usuario lo sepa. El monitor de progreso no desplegará el diálogo si el la tarea se completa dentro del tiempo especificado.
> Si decidimos utilizar un monitor de progreso y la tarea que estamos monitorizando lee desde un stream de entrada, se utiliza la clase ProgressMonitorInputStream.

#### El API de ProgressBar

> Las siguientes tablas listan los métodos y constructores más utilizados de JProgressBar. Otros métodos interesantes están definidos por las clases JComponent y Component

> El API para monitorizador progresos se divide en estas categorías:

> - Seleccionar u Obtener los valores/restricciones de la Barra de Progreso
> - Ajuste Fino de la Apariencia de la Barra de Progreso
> - Configurar un Monitor de Progreso
> - Terminar el Monitor de Progreso

> Seleccionar u Obtener los valores/restricciones de la Barra de Progreso
> Método | Propósito
> --- | ---
> void setValue(int) int getValue() | Selecciona u obtiene el valor actual de la barra de progreso. El valor está limitado por los valores máximo y mínimo.
> double getPercentComplete() | Obtiene el procentaje terminado por la barra de progreso.
> void setMinimum(int) int getMinimum() | Selecciona u obtiene el valor mínimo de la barra de progreso.
> void setMaximum(int) int getMaximum() | Selecciona u obtiene el valor máximo de la barra de progreso.
> void setModel(BoundedRangeModel) BoundedRangeModel getMaximum() | Selecciona u obtiene el modelo utilizado por la barra de progreso. El modelo establece los valores y restricciones de la barra de progreso. Podemos utilizar este método como alternativa a utilizar los métodos de selección u obtención individuales listados arriba.

> Ajuste Fino de la Apariencia de la Barra de Progreso.
> Método | Propósito
> --- | ---
> void setOrientation(int) int getOrientation() | Selecciona u obtiene si la barra de progreso es vertical u horizontal. Los valores aceptados son JProgressBar.VERTICAL o JProgressBar.HORIZONTAL.
> void setBorderPainted(boolean) boolean isBorderPainted() | Selecciona u obtiene si la barra de progreso tiene borde.
> void setStringPainted(boolean) boolean isStringPainted() | Selecciona u obtiene si la barra de progreso meustra el porcentaje. Por defecto, el valor de la cadena de porcentaje es el valor devuelto por getPercentComplete formateado a porcentaje. Podemos cambiar la cadena de porcentaje con setString.
> void setString(String) String getString() | Selecciona u obtiene la cadena de porcentaje.

> Configurar un Monitor de Progreso
> Método | Propósito
> --- | ---
> ProgressMonitor(Component, Object, String, int, int) | Crea un monitor de progreso e inicializa el padre del diálogo, el string descriptivo, la nota de estado y los valores mínimo y máximo.
> void setMinimum(int) int getMinimum() | Selecciona u obtiene el valor mínimo del monitor de progreso.
> void setMaximum(int) int getMaximum() | Selecciona u obtiene el valor máximo del monitor de progreso.
> void setProgress(int) | Actualiza el monitor de progreso.
> void setNote(String) String getNote() | Selecciona u obtiene la nota de estado. Esta nota se muestra en el diálogo. Para omitirla, se proporciona null como el tercer argumento del constructor del monitor.
> void setMillisToPopup(int) int getMillisToPopup() | Selecciona u obtiene el tiempo después del cual el monitor debería desplegar el diálogo sin importar el estado de la tarea.
> void setMillisToDecideToPopup(int) int getMillisToDecideToPopup() | Selecciona u obtiene el tiempo después del cual el monitor debería desplegar el diálogo si la tarea no se ha completado.

> Terminar el Monitor de Progreso
> Método | Propósito
> --- | ---
> close() | Cierra el monitor de progreso. Esto oculta el diálogo.
> boolean isCanceled() | Determina si el usuario ha pulsado el botón Cancel.

#### Ejemplos que monitorizan progresos

> Esta tabla lista ejemplos que utilizan JProgressBar, ProgressMonitor, o ProgressMonitorInputStream, y dónde poder encontrarlos:

> Ejemplo | Dónde se describe | Notas
> --- | --- | ---
> ProgressBarDemo.java | Esta página y Cómo usar Temporizadores | Utiliza una barra de progreso básica para mostrar el progreso de una tarea ejecutandose en un thread separado.
> ProgressMonitorDemo.java | Esta página | Modificación del ejemplo anterior que utiliza un monitor de progreso en vez de una barra de progreso.

Ozito