Pregunta

Estoy en el proceso de crear una interfaz gráfica de usuario en Netbeans 6.1 para mi proyecto de diseño de alto nivel, pero me he encontrado con un obstáculo molesto. Ventanas temporales como mi emergente de inicio de sesión y otros planteo desaparece cuando lo cuento. He estado investigando cómo resolver este durante unos 2 meses en un off. Incluso he loca un hilo separado para mi Pop Up pero todavía no trabajará .... la única forma en que va a desaparecer si, literalmente, no ensucie con cualquiera de los otros componentes de la GUI .... mi código de ejemplo debería ayudar a describir mi ira ... no me importa el código de sombra, que era para propósitos de prueba, lo que ayuda aún no ha obviamente.

//This method is called once a user presses the "first" login button on the main GUI
public synchronized void loginPopUpThread() {
    doHelloWorld = new Thread(){
        @Override
        public synchronized void run()
        {
            try
            {
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(true);
                    System.out.println("waitin");
                    doHelloWorld.wait();
                    System.out.println("Not Sleepin..");
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(false);
            }
            catch (InterruptedException e)
            {
            }
        }
    };
    doHelloWorld.start();

//This is called when the "second" loginB is pressed and the password is correct...
public synchronized void notifyPopUp() {
    synchronized(doHelloWorld) {

        doHelloWorld.notifyAll();
        System.out.println("Notified");
    }
}

También he intentado oscilación Utilidades pero tal vez he implementado mal, ya que es la primera vez que el uso de ellos. En esencia, hace lo mismo que el código anterior excepto la ventana se congela cuando se pone a esperar, que el código anterior doesnt hacer:

javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public synchronized void run() {
            try
            {
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(true);
                    System.out.println("waitin");
                    wait();
                        System.out.println("Not Sleepin.");
                        loginPopUpFrame.pack();
                       loginPopUpFrame.setVisible(false);
            }
            catch (InterruptedException e)
            {
            }
        }
    });

Por favor me ayude !!!

¿Fue útil?

Solución

Las reglas generales:

  • No manipular los componentes GUI en las discusiones arbitrarias; Siempre arreglos para manipularlos en el hilo de eventos
  • Nunca espere o dormir en el interior del hilo de eventos (así, nunca dentro de código enviado a invokeLater ())

Así que la respuesta a cómo resolver este problema es "de otra manera" ...

De pie detrás del problema un poco, ¿qué es en realidad estás tratando de hacer? Si lo que desea es un cuadro de diálogo de inicio de sesión que esperar a que el usuario introduzca el nombre de usuario y contraseña, ¿hay una razón para no sólo tiene que utilizar un JDialog modal (después de todo, eso es lo que está ahí para ...).

Si realmente quiere un poco de hilo arbitraria a esperar una señal para cerrar la ventana / manipular la interfaz gráfica de usuario, a continuación, tiene que hacer la espera en el otro hilo y, a continuación, hacer que SwingUtilities.invokeLater llamada hilo () con el código real manipulación de interfaz gráfica de usuario.

P.S. En realidad, hay algunos métodos de manipulación de interfaz gráfica de usuario que es seguro para llamar desde otros hilos, por ejemplo, llamadas que son "sólo la creación de una etiqueta" a menudo son seguros. Pero que las llamadas son seguros no es muy bien definido, por lo que lo mejor es sólo para evitar el problema en la práctica.

Otros consejos

Los componentes Swing sólo deben ser manipulados por el hilo de eventos oscilación de despacho.

SwingUtilites clase tiene métodos para presentar tareas para el hilo de despacho.

Es difícil de diagnosticar su problema. No estoy seguro de lo que estás tratando de hacer con la esperar métodos , pero recomiendo dejando esperar / notificar solo.

Este código tiene dos cuadros - cuando se crea un segundo marco, la primera se podrá ver hasta que lo cierre

.
public class SwapFrames {

  private JFrame frame;

  private JFrame createMainFrame() {
    JButton openOtherFrameButton = new JButton(
        "Show other frame");

    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new FlowLayout());
    contentPane.add(openOtherFrameButton);
    frame.pack();

    openOtherFrameButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            onClickOpenOtherFrame();
          }
        });

    return frame;
  }

  private void onClickOpenOtherFrame() {
    frame.setVisible(false);

    JFrame otherFrame = new JFrame();
    otherFrame
        .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    otherFrame.setContentPane(new JLabel(
        "Close this to make other frame reappear."));
    otherFrame.pack();
    otherFrame.setVisible(true);
    otherFrame.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosed(WindowEvent e) {
        frame.setVisible(true);
      }
    });
  }

  public static void main(String[] args) {
    JFrame frame = new SwapFrames().createMainFrame();
    frame.setVisible(true);
  }

}

Debido a que no veo evidencia de su presencia en el código, me voy a leer sobre el uso de detectores de eventos lugar de tratar de 'esperar' a que el código para terminar.

No está del todo claro lo que estamos tratando de lograr, pero que podría ser mejor con un cuadro de diálogo modal:

public class DialogDemo {

  public JFrame createApplicationFrame() {
    JButton openDialogButton = new JButton("Open Dialog");

    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container container = frame.getContentPane();
    container.setLayout(new FlowLayout());
    container.add(openDialogButton);
    frame.pack();

    openDialogButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            onOpenDialog(frame);
          }
        });

    return frame;
  }

  private void onOpenDialog(JFrame frame) {
    JDialog dialog = createDialog(frame);
    dialog.setVisible(true);
  }

  private JDialog createDialog(JFrame parent) {
    JButton closeDialogButton = new JButton("Close");

    boolean modal = true;
    final JDialog dialog = new JDialog(parent, modal);
    dialog
        .setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    Container container = dialog.getContentPane();
    container.add(closeDialogButton);
    dialog.pack();
    dialog.setLocationRelativeTo(parent);

    closeDialogButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            dialog.setVisible(false);
          }
        });

    return dialog;
  }

  public static void main(String[] args) {
    new DialogDemo().createApplicationFrame().setVisible(
        true);
  }

}

¿Qué hacer simplemente:

//This method is called once a user presses the "first" login button on the main GUI
public void loginPopUpThread() {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            loginPopUpFrame.pack();
            loginPopUpFrame.setVisible(true);
        }
    };
}

//This is called when the "second" loginB is pressed and the password is correct...
public void notifyPopUp() {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            loginPopUpFrame.setVisible(false);
        }
    };
}

Lo que realmente quiere estar utilizando es un referente JDialog.

Nota, bits de este se quedan fuera. Es su tarea / proyecto.

public void actionPerformed(ActionEvent e)
{
   // User clicked the login button
   SwingUtilities.invokeLater(new Runnable()
   {
       public void run()
       {
         LoginDialog ld = new LoginDialog();
         // Will block
         ld.setVisible(true);
       }
   });
}

public class LoginDialog extends JDialog
{
    public LoginDialog()
    {
        super((Frame)null, "Login Dialog", true);

        // create buttons/labels/components, add listeners, etc
    }

    public void actionPerformed(ActionEvent e)
    {
       // user probably clicked login
       // valid their info
       if(validUser)
       {
          // This will release the modality of the JDialog and free up the rest of the app
          setVisible(false);
          dispose();
       }
       else
       {
          // bad user ! scold them angrily, a frowny face will do
       }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top