miércoles, 23 de junio de 2010

Crear una barra de progreso en Java



Todos sabemos de la importancia de la retroalimentación cuando estamos utilizando una aplicación informática: en todo momento, el usuario debe estar informado del estado de las operaciones que se están realizando. Mucho más cuando una operación tarda mucho en realizarse, como la copia de archivos de gran volumen, ...
Un elemento imprescindible para dar ese tipo de información es la barra de progreso. Se va a explicar cómo hacer ésto en Java.


 

El código


Constructor que crea un JPanel y colocación los elementos gráficos dentro.
 public Progress() {
  super("Progress");
  
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pane = new JPanel();
  pane.setLayout(new FlowLayout());
  current = new JProgressBar(0, 2000); // Crear un JProgressBar con valores 0-2000
  current.setValue(0); // Fijar valor por defecto.
  current.setStringPainted(true); // Mostrar valor numérico del progreso de la barra
  pane.add(current);
  setContentPane(pane);
  }


Médoto para calcular los Valores del progreso de la barra
Aquí debemos decidir, qué criterios se seguirán para determinar el valor de la barra en cada momento, ejemplo: MB de datos copiados, operaciones realizadas, ... En éste caso, al tratarse de un ejemplo sencillo, usaremos un contador de 0 a 2000:

 public void iterate() {
  while (num < 2000) {
  current.setValue(num); // Asignar un valor a la barra de progreso.
  try {
  Thread.sleep(1000);
  } catch (InterruptedException e) { }
  num += 95;
  }
  } 


Método Main
 public static void main(String[] arguments) {
  Progress frame = new Progress(); // Crea un objeto Progress (constructor visto antes).
  frame.pack(); 
  frame.setVisible(true);
  frame.iterate(); // LLamada al método iterate (visto antes).
  }


Código completo
import java.awt.*;
  import java.awt.event.*;
  import javax.swing.*; 
public class Progress extends JFrame {
JProgressBar current;
  JTextArea out;
  JButton find;
  Thread runner;
  int num = 0;
public Progress() {
  super("Progress");
  
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pane = new JPanel();
  pane.setLayout(new FlowLayout());
  current = new JProgressBar(0, 2000);
  current.setValue(0);
  current.setStringPainted(true);
  pane.add(current);
  setContentPane(pane);
  }

public void iterate() {
  while (num < 2000) {
  current.setValue(num);
  try {
  Thread.sleep(1000);
  } catch (InterruptedException e) { }
  num += 95;
  }
  }
public static void main(String[] arguments) {
  Progress frame = new Progress();
  frame.pack();
  frame.setVisible(true);
  frame.iterate();
  }
  }

 


Fuente

http://www.java-tips.org

 




30 Comentarios:

Jossimar dijo...

Hola muchas gracias por el aporte esta excelente. Pero como hago para agregar este codigo en la transferencia de archivos usando Sockets en Java? Y ke el me muestre el tiempo aproximado para completar la transferencia

Felipe dijo...

Hola Jossimar.

Te voy a poner un ejemplo sencillo.

Tenemos el siguiente código en el que se envían tres flujos de datos (en tu caso son archivos) a través de sockets. Debes inicializar el JProgressBarr en el método Progress y luego ir asignándole valores a la barra de progreso en cada iteracción. Ésto último se hace en la línea current.setValue(num) .


public void iterate() {

ServerSocket skServidor = new ServerSocket( PUERTO );

System.out.println("Escucho el puerto " + PUERTO );

for ( int numCli = 0; numCli < 3; numCli++; ) {

Socket skCliente = skServidor.accept();

System.out.println("Sirvo al cliente " + numCli);

OutputStream aux = skCliente.getOutputStream();

DataOutputStream flujo= new DataOutputStream( aux );

flujo.writeUTF( "Hola cliente " + numCli );

skCliente.close();

current.setValue(num); // Aquí se asigna el valor a la barra de progreso
}

}


public Progress() {
...
current = new JProgressBar(0, 2); // Crear un JProgressBar con valores 0-2000
current.setValue(0); // Fijar valor por defecto.
...
}



Espero que te sirva. Si tienes alguna pregunta, no dudes en decírmelo.

Saludos.

Jossimar dijo...

Hola muchas gracias por la ayuda: pero no me keda muy claro... No se en ke momento tengo ke llamar al metodo de la Barra de progresso. Estoy perdido mira este es mi codigo... El cliente recibe el archivo del servidor y kiero ke en el mismo cliente aparesca la barra pero no pude con el codigo ke me enviaste... No entiendo el trabajo de la variable "Num" y kite el Thread.sleep ke tenias en el ejemplo de como crear una barra de progreso

Chek el codigo:

import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.net.*;

public class Progress extends JFrame
{
JProgressBar current;
int num = 0;

ServerSocket server;
Socket connection = null;

DataOutputStream output;
BufferedInputStream bis;
BufferedOutputStream bos;

byte[] receivedData;
int in;
String file;


public Progress()
{
super("Barra de Progreso");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pane = new JPanel();
pane.setLayout(new FlowLayout());
current = new JProgressBar(0, 2000);
current.setValue(0);
current.setStringPainted(true);
pane.add(current);
setContentPane(pane);
}

public void iterate()
{
try{
server = new ServerSocket(1234);
while ( true )
{
connection = server.accept();

if(connection != null)
JOptionPane.showMessageDialog(null,"Se conecto un cliente....");

receivedData = new byte[1024];
bis = new BufferedInputStream(connection.getInputStream());
DataInputStream dis = new DataInputStream(connection.getInputStream());

//se recibe el nombre del fichero
file = dis.readUTF();
file = file.substring(file.indexOf('/')+1,file.length());

//Destino donde se guardara el archivo
bos = new BufferedOutputStream(new FileOutputStream("/home/jossimar/Escritorio/" + file));
while ((in = bis.read(receivedData)) != -1){
bos.write(receivedData,0,in);
}
bos.close();
dis.close();

current.setValue(num);

JOptionPane.showMessageDialog(null, "Archivo (" + file.toString() + ") Recibido satisfactoriamente");
}
}catch (Exception e ) {JOptionPane.showMessageDialog(null,e);}

}


public static void main(String Jossimar[])
{
Progress frame = new Progress();
frame.pack();
frame.setVisible(true);
frame.iterate();
}
}

Jossimar dijo...

Modifico: El servidor recibe el archivo del cliente.....

Felipe dijo...

Hola.

En el ejemplo que te puse, la línea

current.setValue(num);

está incorrecta, sería así:

current.setValue(numCli);


En tu ejemplo, no se si se podría hacer, porque creo que la operación de escritura no la haces de forma iterativa, sino en un solo paso:

while ((in = bis.read(receivedData)) != -1){
bos.write(receivedData,0,in);
}

Si estoy equivocado en esto, dímelo y te intento ayudar.

Saludos.

Jossimar de Leon dijo...

Ya pude lograr realizar lo que queria :D

Felipe dijo...

De acuerdo Jossimar, gracias por comentar.

Anónimo dijo...

vacano el tutorial pero como haria una grafica dinamica en java

Anónimo dijo...

necesito ayuda se lo agradeceria

Felipe dijo...

Hola.

He oído hablar de JFreeChart(http://www.jfree.org/jfreechart/samples.html), que es una librería opensource dedicada a crear gráficas. No te puedo dar una opinión acerca de JFreeChart porque no la he utilizado, pero parece que se utiliza bastante para este propósito. Aquí tienes un tutorial: http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=jfreechart

. Espero que haya ayudado.

Saludos.

Anónimo dijo...

como puedo agrandar la barra porcenjate

Felipe dijo...

Hola.

¿Cómo querrías agrandar la barra de porcentaje?. Yo lo que haría sería fijar el tamaño de la barra de porcentaje al JPane que lo contiene. De ese modo si agrandamos el tamaño del JPane, también aumentaría su tamaño la JProgressbar. Para ellos deberías sustituir la siguiente línea:

pane.setLayout(new FlowLayout());

por ésta:

pane.setLayout(new GridLayout(0, 1));


Espero que te ayude. No obstante, si necesitas algo más concreto, coméntamelo.

Saludos.

Anónimo dijo...

Hola, oye como podría implementarlo para el siguiente código:

modelo.verificarLogeo(vista.getTxtUsuario(), vista.getTxtContrasena());

Estoy implementando MVC y esto es parte del controlador. Lo que hace el código es enviar a un método, que realiza una consulta a la base de datos, dos parámetros tipo String. Cómo podría medir el tiempo de reapuesta desde que se realiza la consulta hasta que trae el resultset con el resultado de la búsqueda. Agradezco la ayuda.

Felipe dijo...

Hola.

Puedes utilizar System.currentTimeMillis. Ejemplo:

double tiempoInicio = System.currentTimeMillis();
//
// Código a medir
//
double tiempoFin = System.currentTimeMillis();
//calculo el tiempo que tardó el código
double tiempo = tiempoFin - tiempoInicio;

Espero que te sirva.

Saludos.

luis dijo...

Hola, muy buen aporte tengo una duda como puedo modificar el tamaño de la barrita?

Gracias, saludos

Felipe dijo...

Hola Luis.

Debes de ajustar el JPanel que contiene el JProgressBar, mediante el método setPreferredSize. Ejemplo:

pane.setPreferredSize(new Dimension(11, 22));

Espero que te sirva.

Anónimo dijo...

Hola, si mira, soy nuevo en todo esto de Java.
Pero para aprender y divertirme me gustaría hacerle una broma a mis amigos.
Mi idea es que aparezca una barra de progreso como que se le esta formateando la PC o algo asi, el mensaje despues se me ocurrirá.
No se si puedes ayudarme :D
Creo que no puedes hacer una barra de progreso de NADA
Pero tal vez si se puede hacer una barra de progreso que demore x segundos(x ejemplo 5 segundos) en llegar al 100%.

Nose si me explico bien, si me puedes ayudar genial.
En realidad mas que nada no es por la broma, sino por aprender. Me gustaria ser programador, estoy estudiando eso pero recien empiezo.
Gracias :D

Felipe dijo...

Hola.

Si estás empezando en el mundo de la programación, te recomendaría que probaras ejemplos muy sencillos, como el "Hola Mundo" (o Hello World) y vayas modificando el código para ir añadiendo más complejidad. Es decir, que juegues un poco y compruebes como la aplicación va cambiando y al mismo tiempo entiendas el código.

Si quieres crear una barra de progreso, este ejemplo te puede servir. Simplemente cámbiale el texto para que la broma sea creíble XD.

Saludos.

Anónimo dijo...

Saludos, estoy empezando en java, quisiera saber como podría optimizar ese código para que el usuario ingrese un numero, y que ese numero sea el valor máximo que cargue en la barra de progreso?

Por ejemplo si el usuario teclea el numero 40, que la barra cargue de 0% hasta el 40%

Felipe dijo...

Hola.

Para que la barra llegue solamente al 40%, debes de modificar el código de la siguiente manera:

- Creamos un JProgressBar de 0 a 100 (debes de modificar el constructor del JProgressBar con los siguientes valores):
current = new JProgressBar(0, 100);

- Modifica el método interate() de la siguiente forma:

public void iterate() {
while (num < 41) {
current.setValue(num);
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
num += 5;
}
}


Lo que he hecho es crear una JProgressBar con 100 divisiones, que la barra incremente su valor de cinco en cinco y que el valor máximo sea 40 (num < 41).

Si quieres que el valor máximo sea variable (osea, que el valor lo indique el usuario), deberás crear una propiedad para guardar este valor:

int numMaximo= 40;

Y luego en la línea del while, modificarla así:

while (num < numMaximo) {


Si tienes alguna duda, puedes preguntarme.

Saludos.

Anónimo dijo...

Hola, buen tutorial, pude entender bien como se realiza la progressbar, pero quede con una duda, en mi caso necesito crear una ventana con un boton donde uso el JFileChooser para elegir un documento word, y este copiarlo en una carpeta aparte y necesito que la progressbar se llene en el tiempo en que el archivo word se copia, como se realizaria esto? mi codigo es este y como lo introduciria, Muchas gracias!

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;


public class Ventana extends javax.swing.JFrame {
JFileChooser select = new JFileChooser();
File folder = new File("C:\\Users\\Clyde\\Desktop\\Hola");

public Ventana() {
initComponents();
}

public void FileCopy(String sourceFile, String destinationFile) {
try {
File inFile = new File(sourceFile);
File outFile = new File(destinationFile);

FileInputStream in = new FileInputStream(inFile);
FileOutputStream out = new FileOutputStream(outFile);

int c;
while( (c = in.read() ) != -1)
out.write(c);

in.close();
out.close();
} catch(IOException e) {
System.err.println("Hubo un error de entrada/salida!!!");
}
}

public String Ramdon(){
int num = (int)(Math.random()*1000);
String nuevo = Integer.toString(num);
return nuevo;
}

//Este es el ActionListener del Boton con el JFileChooser

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
FileNameExtensionFilter filtro=new FileNameExtensionFilter("Archivos Office","doc","ppt","xls","docx");
select.setFileFilter(filtro);
int file=select.showDialog(null,"Seleccionar");
if(file==JFileChooser.APPROVE_OPTION){
File item = select.getSelectedFile();
folder.mkdirs();
String archivo = Ramdon()+select.getSelectedFile().getName();
FileCopy(item.getPath(),folder+"\\"+archivo);
}

}

¡Gracias si puedes responder!

Felipe dijo...

Hola.

Échale un vistazo al siguiente ejemplo: http://2k8618.blogspot.com.es/2012/01/file-copier-java-swing-jprogressbar.html .

Fíjate en la clase task.java, que es lo importante para hacer lo que tu quieres. Si tienes dudas, pregúntame.

Saludos

Anónimo dijo...

Solo le falta colocar al codigo la sentencia

public static void main(String[] args)
{
Progress frame = new Progress();
frame.pack();

frame.setLocationRelativeTo(null);

frame.setVisible(true);
frame.iterate();
}

Para que la barra aparezca centrada en la pantalla

Felipe dijo...

Gracias por la puntualización. Efectivamente, frame.setLocationRelativeTo(null); sirve para centrar el frame..

Saludos.

Alacran Moralez dijo...

muy buen codigo hermano, solo una pregunta
para que sirve la parte que aumenta en 95 al contador:

num += 95;

solo se que si lo quito ya no avanza la barra :D

Felipe Martínez D. dijo...

Hola.

Ese número son las unidades que avanza la barra en cada iteración. Si quieres que la barra avance menos en el mismo tiempo puedes bajar ese valor, y viceversa.

Saludos y gracias por comentar.

Alex Mercado dijo...

Hola
Espero puedas ayudarme, mi programa carga un archivo a través de un JMenuItem, antes de ello, crea la ventana con el JProgressBar para que, mientras escribe las lineas del archivo indique el porcentaje de lectura, el problema es que la ventana se queda en blanco y solo muestra el porcentaje final, mas no el avance.

Felipe Martínez D. dijo...

Hola Alex.

Muéstrame como implementas el método iterate() .

Saludos.

Anónimo dijo...

Buenas como hago que por medio de un boton se cargue la ventana con toda la barra de progreso. Gra

Felipe Martínez D. dijo...

Hola. Por favor, explica con más detalle qué es lo que necesitas e intentaré ayudarte. Un saludo.

Publicar un comentario

Felinfo: Java, Linux, Virtualización. Open Source.  ©Template Blogger Green by Dicas Blogger .

TOPO