2010-08-12 28 views
6

Esto es para los expertos en swing que hay. He dedicado un tiempo considerable a este problema, así que me va a tomar algunas líneas explicar el problema.Barra de progreso progresiva de Java del problema EDT

Tengo una aplicación java swing independiente (java 6). En mi aplicación, tengo un marco con un grupo de botones de opción. Tengo una sola acción vinculada a todos los botones del grupo. La acción comprueba qué botón de opción se selecciona y realiza algún trabajo. El "trabajo" implica algunos cálculos de fondo, así como algunos cuadros en otros dos marcos en mi aplicación. El cálculo de fondo es multihilo.

Me gustaría mostrar una barra de progreso cuando el usuario selecciona uno de los botones de opción. Sin embargo, cuando se selecciona un botón de opción mientras se está ejecutando la acción del botón de opción, la barra de progreso nunca aparece. He intentado las barras de progreso del tipo jdialog, los paneles de vidrio, etc. Ninguno aparece hasta que el "trabajo" está completo. Esto parece ser porque Swing no termina de pintar el botón de radio hasta que se completa el "trabajo" en la acción correspondiente. Y dado que el EDT solo hace una cosa a la vez, nunca se muestra el cuadro de diálogo de la barra de progreso (o panel de cristal).

Intenté utilizar un SwingWorker para hacer todo este "trabajo". Inicie la barra de progreso (o active un panel de cristal), inicie SwingWorker y cierre la barra de progreso (o desactive el panel de cristal) en el método done() para SwingWorker. Esto parece traer bien la barra de progreso, pero la pintura que es parte del "trabajo" a veces no se completa, dejándome con algunos artefactos de pintura (el método paintComponent es bastante complicado, así que no quiero reproducirlo aquí). Los artefactos desaparecen si cambio el tamaño de la ventana. De hecho, esto sucede si uso una clase que amplíe Thread en lugar de SwingWorker también. Esto es todo porque Swing no es seguro para los hilos y estoy tratando de hacer trabajos de GUI a partir de un hilo que no sea el EDT. Yo entiendo esa parte.

¿Qué debo hacer? El "trabajo" tarda unos 30 segundos y parece que falta mucho para que aparezca sin mostrar al usuario algún tipo de indicación de que el programa está funcionando. También he intentado cambiar el cursor a un cursor de espera y he tenido los mismos problemas que antes. Lo único que puedo hacer es desactivar el marco y establecer el título del marco como texto "trabajando ..."

¿Alguien ha visto este problema antes?

Respuesta

4

Creo que tienes razón para hacer el trabajo en el hilo SwingWorker, pero no deberías intentar pintar allí.

Me inclinaría a:

  • hacer que ésta se ActionListener() de la barra de progreso, fijar del SwingWorker salga

  • Hacer que el subproceso de trabajo hacer el trabajo, y periódicamente llamar repaint() en el componente de barra de progreso (se garantiza que es seguro para subprocesos)

  • Barra de progreso tiene su propio componente de pintura (que se llamará automáticamente en el EDT). Si es necesario, esto puede leer alguna variable que se actualiza por el hilo del trabajador para medir el progreso

  • Cuando termina el hilo del trabajador, llámelo a invocarLater() para ejecutar una función final de cierre en el EDT, que ocultará el barra de progreso y hacer cualquier otra limpieza relacionados con interfaz gráfica de usuario/muestran un mensaje de finalización para el usuario, etc.

+0

¿Cómo me aseguro de que el EDT no haga ninguna otra pintura hasta que se complete el trabajo en el subproceso de SwingWorker? El trabajo que se puede realizar en segundo plano debe completarse antes de que mis cuadros se vuelvan a pintar. – Anu

+0

¡Gracias! Lo tengo para trabajar. – Anu

4

Cuando movió el trabajo del EDT al columpio (lo cual era lo correcto), parece que tanto el trabajo como la pintura se movieron al columpio. La pintura debería seguir ocurriendo en el EDT. Puede lograrlo utilizando SwingUtilities.invokeLater para invocar un repintado desde el hilo de fondo, o usando el SwingWorker.publish(V...), que tomará las notificaciones de su hilo de trabajo y las pondrá a disposición en el EDT a través del método de plantilla SwingWorker.process(V...) (que anula). Su anulación process puede manejar las notificaciones intermedias volviendo a pintar una parte de la pantalla, actualizando el progreso o realizando alguna otra acción apropiada como desee. Cualquier cambio en la interfaz de usuario hecho aquí será visible sin esperar a que se complete el resto del trabajo.

+0

Gracias, tengo la solución de Mikera a trabajar, pero su comentario acerca de haber movido la pintura a la EDT, así estimulado la ¡Cómo he cambiado las cosas! – Anu

+0

Utilizar SwingWorker.publish() en el hilo de trabajo es el camino a seguir, creo. – keuleJ