Make a swing thread that show a “Please Wait” JDialog

前端 未结 3 1085
不思量自难忘°
不思量自难忘° 2020-12-09 19:10

The problem is this:
I\'ve a swing application running, at a certain point a dialog requires to insert username and password and to press \"ok\".
I would like tha

3条回答
  •  Happy的楠姐
    2020-12-09 19:46

    Consider using a SwingWorker to do your background work, and then closing the dialog either in the SwingWorker's done() method or (my preference) in a PropertyChangeListener that is added to the SwingWorker.

    e.g.,

    import java.awt.BorderLayout;
    import java.awt.Dialog.ModalityType;
    import java.awt.Window;
    import java.awt.event.ActionEvent;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;    
    import javax.swing.*;
    
    public class PleaseWaitEg {
       public static void main(String[] args) {
          JButton showWaitBtn = new JButton(new ShowWaitAction("Show Wait Dialog"));
          JPanel panel = new JPanel();
          panel.add(showWaitBtn);
          JFrame frame = new JFrame("Frame");
          frame.getContentPane().add(panel);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
    
       }
    }
    
    class ShowWaitAction extends AbstractAction {
       protected static final long SLEEP_TIME = 3 * 1000;
    
       public ShowWaitAction(String name) {
          super(name);
       }
    
       @Override
       public void actionPerformed(ActionEvent evt) {
          SwingWorker mySwingWorker = new SwingWorker(){
             @Override
             protected Void doInBackground() throws Exception {
    
                // mimic some long-running process here...
                Thread.sleep(SLEEP_TIME);
                return null;
             }
          };
    
          Window win = SwingUtilities.getWindowAncestor((AbstractButton)evt.getSource());
          final JDialog dialog = new JDialog(win, "Dialog", ModalityType.APPLICATION_MODAL);
    
          mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
    
             @Override
             public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals("state")) {
                   if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
                      dialog.dispose();
                   }
                }
             }
          });
          mySwingWorker.execute();
    
          JProgressBar progressBar = new JProgressBar();
          progressBar.setIndeterminate(true);
          JPanel panel = new JPanel(new BorderLayout());
          panel.add(progressBar, BorderLayout.CENTER);
          panel.add(new JLabel("Please wait......."), BorderLayout.PAGE_START);
          dialog.add(panel);
          dialog.pack();
          dialog.setLocationRelativeTo(win);
          dialog.setVisible(true);
       }
    }
    

    Notes:

    • A key concept is to set everything up, add the PropertyChangeListener, get the SwingWorker running, all before displaying the modal dialog, because once the modal dialog is shown, all code flow from the calling code is frozen (as you've found out).
    • Why do I prefer the PropertyChangeListener to using the done method (as Elias demonstrates in his decent answer here, which I've up-voted) -- using the listener provides more separation of concerns, looser coupling. This way the SwingWorker has to know nothing of the GUI code that is using it.

提交回复
热议问题