ventana sirve showmessagedialog showinputdialog que para mensaje emergente ejemplos dialogo confirmacion cerrar boton java multithreading swing modal-dialog jdialog

sirve - mensaje de confirmacion java



El diálogo modal de Swing se niega a cerrar, ¡a veces! (4)

Entonces resulta que lo que sucede cuando se muestra () / setVisible (true) un cuadro de diálogo modal es que se ejecuta un segundo ciclo de envío de eventos dentro de la llamada para mostrar / setVisible. Lo cual tiene perfecto sentido una vez que lo sabes. Con eso en mente, terminé con este código:

public void runBlockingTask(final String taskName, final BlockingTask bt) { SwingUtilities.invokeLater(new Runnable() { public void run() { new Thread("Worker Thread: " + taskName) { @Override public void run() { bt.run(); progressDialog.setVisible(false); } }.start(); }}); // NB This causes the event dispatch loop to be run inside this call, // which is why we need to put everything after setVisible into an // invokeLater. progressDialog.setVisible(true); }

// This is supposed to show a modal dialog and then hide it again. In practice, // this works about 75% of the time, and the other 25% of the time, the dialog // stays visible. // This is on Ubuntu 10.10, running: // OpenJDK Runtime Environment (IcedTea6 1.9) (6b20-1.9-0ubuntu1) // This always prints // setVisible(true) about to happen // setVisible(false) about to happen // setVisible(false) has just happened // even when the dialog stays visible. package modalproblemdemo; import java.awt.Frame; import javax.swing.JDialog; import javax.swing.SwingUtilities; public class Main { public static void main(String[] args) { final Dialogs d = new Dialogs(); new Thread() { @Override public void run() { d.show(); d.hide(); } }.start(); } static class Dialogs { final JDialog dialog; public Dialogs() { dialog = new JDialog((Frame) null, "Hello World", /*modal*/ true); dialog.setSize(400, 200); } public void show() { SwingUtilities.invokeLater(new Runnable() { public void run() { dialog.setLocationRelativeTo(null); System.out.println("setVisible(true) about to happen"); dialog.setVisible(true); }}); } public void hide() { SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("setVisible(false) about to happen"); dialog.setVisible(false); System.out.println("setVisible(false) has just happened"); }}); } } }


Es claramente un tipo de condición de carrera. No creo que sea tan simple como la respuesta de Erick Robertson. El código show() de Dialog show() es bastante complicado, contiene alguna lógica especial para ser llamado desde el hilo de envío del evento y también publica eventos en la cola del evento. Tal vez el orden en que se publican los eventos se ve afectado de alguna manera por los retrasos en el hilo.

Tal vez lo que necesita es SwingUtilities.invokeAndWait() , de esta manera se garantiza que setVisible(true) haya terminado la ejecución antes de llamar a setVisible(false) . Como señaló Skip Head, invokeAndWait se bloqueará hasta que se cierre el diálogo.

¿Y por qué lo necesitas de todos modos?

EDITAR: Este es mi escenario de lo que está sucediendo:

  1. usted llama a d.show () que publica el setVisible(true)
  2. el hilo se pone tan dormido por el programador y EDT entra en acción y comienza a ejecutar el primer evento
  3. EDT es echado antes de que la primera tarea haya terminado y publicado un evento real que muestra el diálogo
  4. su hilo ejecuta d.hide () que publica el evento setVisible (falso). El hilo ha terminado y EDT entra en acción
  5. EDT terminó la primera tarea, coloca su evento de muestra en la cola del evento
  6. Va al próximo evento y, ¡voila, es el evento setVisible (falso)!
  7. Desordena el estado completo del diálogo y permanece visible e insensible.

EDIT2: Parece que ProgressMonitor tiene la funcionalidad que intenta implementar.


Podría tratar de dispose() el diálogo en lugar de ocultarlo, pero eso requeriría que lo reconstruya si quisiera volver a mostrarlo.


Un poco de tiempo de espera (100 ms) entre setVisible (verdadero) y setVisible (falso) resuelve el problema en algunos casos. ver también https://bugs.openjdk.java.net/browse/JDK-5109571 Y cuando se trata de usar dispose en lugar de setVisible (falso), no parece haber una condición de carrera