【问题标题】:Dialog isn't responsive while SwingWorker works in the backgroundSwingWorker 在后台工作时对话框没有响应
【发布时间】:2013-03-09 21:38:12
【问题描述】:

基本上我得到了一个以 main 方法作为入口点的 JFrame。在这个主要方法中,程序必须下载一些图像。

为了通知用户程序将随时启动,我想显示一个简单的对话框。

如果我将对话框设置为模态。我必须在启动程序后关闭它才能触发下载。

如果我将它设置为非模态,它会在下载时显示对话框,但它不是响应式的。该对话框甚至不再绘制我的 JLabel 说“请稍候...”。

//...
public static void main(String args[]) 
{
    java.awt.EventQueue.invokeLater
    (
        new Runnable() 
        {
            @Override
            public void run() 
            {
                ImageLoadingWorker ilw = new ImageLoadingWorker();

                ilw.execute();

                new MainFrame().setVisible(true);
            }
        }
    );
}

static class ImageLoadingWorker extends SwingWorker<Void, Void>
{ 
    JDialog dialog ;

    public ImageLoadingWorker()
    {
        dialog = new ImageLoadingDialog(null, false);
        dialog.setVisible(true);
    }

    @Override
    protected Void doInBackground()
    {
        ImageLoading.getInstance() ; // download is triggered
        return null;
    }

    @Override
    protected void done()
    {
        dialog.dispose() ;
    }
}
//...

【问题讨论】:

    标签: java swing swingworker java-web-start


    【解决方案1】:

    我相信解决方案很简单:您需要先开始下载 SwingWorker,然后显示 modal 对话框。

    即,

    public static void main(String args[]) 
    {
        java.awt.EventQueue.invokeLater
        (
            new Runnable() 
            {
                @Override
                public void run() 
                {
                    ImageLoadingWorker ilw = new ImageLoadingWorker();
    
                    // add a PropertyChangeListener to the SwingWorker
                    // when the PCL tells you that the SwingWorker is done, show the mainFrame.
    
                    ilw.execute();
    
                    // .... code for showing the dialog is here.
    
                    //  new MainFrame().setVisible(true);  // done in PCL
                }
            }
        );
    }
    

    更具体的例子:

    import java.awt.Dimension;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JProgressBar;
    import javax.swing.SwingWorker;
    
    public class SwingWorkerEg {
       public static void main(String args[]) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             @Override
             public void run() {
    
                // first set everything up
    
                final MainFrame mainFrame = new MainFrame();
                final SomeDialog someDialog = new SomeDialog(mainFrame);
    
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                mainFrame.pack();
                mainFrame.setLocationRelativeTo(null);
                someDialog.pack();
                someDialog.setLocationRelativeTo(null);
    
                // create SwingWorker and its PropertyChangeListener
                ImageLoadingWorker ilw = new ImageLoadingWorker();
                ilw.addPropertyChangeListener(new PropertyChangeListener() {
    
                   @Override
                   public void propertyChange(PropertyChangeEvent pcEvt) {
                      // since SwingWorker.StateValue is an enum, can use ==
                      if (SwingWorker.StateValue.DONE == pcEvt.getNewValue()) {
    
                         // when *done*, get rid of dialog, and show main JFrame
    
                         someDialog.setVisible(false);
                         mainFrame.setVisible(true);
                      }
                   }
                });
    
                // first start SwingWorker
                ilw.execute();
    
                // And only *after* starting the SW, show the modal dialog
                someDialog.setVisible(true);
             }
          });
       }
    }
    
    class ImageLoadingWorker extends SwingWorker<Void, Void> {
       private static final long SLEEP_TIME = 5 * 1000;
    
       @Override
       protected Void doInBackground() throws Exception {
          // simulate long-running process
          Thread.sleep(SLEEP_TIME);
          return null;
       }
    }
    
    // bad example -- shouldn't extend JDialog!
    class SomeDialog extends JDialog {
       private static final int PREF_W = 300;
       private static final int PREF_H = 60;
    
       public SomeDialog(JFrame frame) {
          super(frame, "Some Dialog", ModalityType.APPLICATION_MODAL);
          JProgressBar progressBar = new JProgressBar();
          progressBar.setIndeterminate(true);
          add(progressBar);
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    }
    
    // bad example -- shouldn't extend JFrame!
    class MainFrame extends JFrame {
       private static final int PREF_W = 400;
       private static final int PREF_H = PREF_W;
    
       public MainFrame() {
          super("Main Frame");
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    }
    

    编辑:
    请记住,永远不要doInBackground() 中创建或显示对话框。那是在 Swing 事件线程之外,没有 Swing GUI 代码可以进入那个方法。

    【讨论】:

      猜你喜欢
      • 2013-07-19
      • 2018-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多