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

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

问题描述

基本上我得到了一个以 main 方法作为入口点的 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天全站免登陆