El paquete Swing proporciona tres clases para ayudar a crear GUIs que monitoricen y muestren el progreso de tareas de larga duración:
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:Abajo está el código de ProgressBarDemo.java que crea y configura la barra de proceso:
Intenta esto:
- Compila y ejecuta la aplicación. El fichero fuente es ProgressBarDemo.java. También necesitarás LongTask.java y SwingWorker.java.
- 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.
...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 <= maximumSi 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.
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.Después el ejemplo crea el monitor de progreso, y lo configura:
- 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.
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.
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 decidimos utilizar un monitor de progreso y la tarea que estamos monitorizando lee desde un stream de entrada, se utiliza la clase ProgressMonitorInputStream.
- 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.
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 ComponentEl 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.
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.