SwingWorker在后台工作时对话框无响应 [英] Dialog isn't responsive while SwingWorker works in the background

查看:78
本文介绍了SwingWorker在后台工作时对话框无响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Basically I got a JFrame with a main method as entry point. In this main method the program has to download some images.

为了通知用户该程序将在任何时候启动,我想显示一个简单的对话框.

To inform the user that the program is going to start any minute I want to display a simple dialog.

如果将对话框设置为模式对话框.启动程序以触发下载后,我必须关闭它.

If I set the dialog to modal. I got to close it after starting the program to trigger the download.

如果我将其设置为非模态,它将显示下载时的对话框,但这并不具有响应性.该对话框甚至不再画我的JLabel说请稍候...".

If I set it to non-modal it displays the dialog for the time of the download, but it's not repsonsive. The dialog doesn't even paint my JLabel saying "Please wait..." anymore.

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

推荐答案

我认为解决方案很简单:您需要先启动SwingWorker下载,然后显示 modal 对话框.

I believe that the solution is easy: You need to start your download, your SwingWorker, first, and then show the modal dialog.

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代码.


Remember, never create or display the dialog in doInBackground(). That's off the Swing event thread, and no Swing GUI code can go in that method.

这篇关于SwingWorker在后台工作时对话框无响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆