Domanda

Sono nel processo di creazione di una GUI in NetBeans 6.1 per il mio progetto di design di alto livello, ma ho incontrato un intoppo fastidioso. Finestre temporanei come il mio PopUp login e altri wont scompaiono quando lo dico. Ho fatto ricerche come risolvere questo per circa 2 mesi su un off. Ho anche pazzo un thread separato per il mio Pop Up ma non lo ancora del lavoro .... l'unico modo in cui scompare se ho letteralmente poteva pasticciare con uno qualsiasi degli altri componenti GUI .... il mio codice di esempio dovrebbe aiutare descrivere il mio rabbia ... non mente il codice ombra, era a scopo di test, che l'aiuto ovviamente di poco.

//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");
    }
}

Inoltre ho provato a battente Utilità ma forse ho implementato sbagliato in quanto è la prima volta che li utilizzano. Lo fa essenzialmente la stessa cosa come il codice di cui sopra, tranne la finestra si blocca quando si arriva ad aspettare che il codice sopra doesnt fare:

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)
            {
            }
        }
    });

PLEASE HELP ME !!!

È stato utile?

Soluzione

Regole empiriche:

  • Non manipolare componenti GUI in discussioni arbitrarie; sempre in modo di manipolarli nel thread evento
  • Mai aspettare o dormire all'interno thread evento (così, il codice non all'interno inviato a invokeLater ())

Quindi, la risposta a come risolvere questo problema è "un altro modo" ...

In piedi, schiena dal problema un po ', che cosa è che si sta effettivamente cercando di fare? Se si desidera solo una finestra di login per attendere che l'utente di inserire nome utente e password, è lì un motivo per non usare solo un JDialog modale (dopo tutto, questo è quello che è lì per ...).

Se davvero si vuole un po 'di thread arbitrario di attendere un segnale per chiudere la finestra / manipolare la GUI, allora si ha bisogno di fare l'attesa in altro thread , e poi fare che chiamata filo SwingUtilities.invokeLater () con il codice di manipolazione GUI.

P.S. In realtà ci sono alcuni metodi di manipolazione GUI che è sicuro chiamare da altri thread, ad esempio le chiamate che sono "solo impostando un'etichetta" sono spesso al sicuro. Ma quali chiamate sono sicuri non è molto ben definito, quindi è meglio solo per evitare il problema, in pratica.

Altri suggerimenti

I componenti Swing devono essere manipolati solo dal thread evento altalena spedizione.

SwingUtilites classe ha i metodi per presentare le attività al thread spedizione.

E 'difficile diagnosticare il problema. Non sono sicuro di quello che stai cercando di fare con il attendere metodi , ma vi consiglio di lasciare attendere / avvisare da solo.

Questo codice ha due fotogrammi - quando si crea un secondo telaio, il primo è nascosto fino a quando lo si chiude

.
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);
  }

}

Perché io non vedo alcuna prova di loro nel codice, ho intenzione di suggerire di leggere su utilizzando listener di eventi piuttosto che cercare di 'attesa' per il codice per terminare.

Non è del tutto chiaro che cosa si sta cercando di raggiungere, ma si potrebbe essere meglio con una finestra di dialogo modale:

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);
  }

}

Che ne dite di fare semplicemente:

//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);
        }
    };
}

Che cosa si vuole veramente di utilizzare è una scelta obbligatoria JDialog.

Nota, bit di questo sono lasciati fuori. E 'il vostro lavoro / progetto.

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
       }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top