gui在调用SwingWorker方法时冻结get()

时间:2014-01-31 13:03:33

标签: java swing user-interface progress-bar swingworker

class ProgressBarSwingWorker extends SwingWorker<Void, Void>
    {
        private int byteWritten = 0;
        private String downloadDir = "";
        private String fileAddress = "";
        private String fileName = "";
        private int fileSize;

        public void fileUrlReadAndDownload(String fileAddress, String downloadDir)
        {
            OutputStream outStream = null;
            URLConnection uCon = null;
            InputStream is = null;
            try
            {
                message.setText(fileName + "in Update");
                URL Url;
                byte[] buf;
                int byteRead;
                Url = new URL(fileAddress);
                outStream = new BufferedOutputStream(new FileOutputStream(downloadDir));
                uCon = Url.openConnection();
                is = uCon.getInputStream();
                buf = new byte[size];
                while ((byteRead = is.read(buf)) != -1)
                {
                    outStream.write(buf, 0, byteRead);
                    byteWritten += byteRead;
                    pbar.setValue(byteWritten);
                    frame.repaint();
                }

                message.setText("update finish");
            } catch (Exception e)
            {
                message.setText("server is not runing.");
                e.printStackTrace();
            } finally
            {
                try
                {
                    is.close();
                    outStream.close();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }

        public ProgressBarSwingWorker(String fileAddress, String downloadDir, String fileName, int fileSize)
        {
            this.fileAddress = fileAddress;
            this.downloadDir = downloadDir;
            this.fileName = fileName;
            this.fileSize = fileSize;
        }

        @Override
        protected Void doInBackground() throws Exception
        {
            pbar.setMaximum(fileSize);
            fileUrlReadAndDownload(fileAddress, downloadDir);

            return null;
        }

        @Override
        protected void done()
        {
            try
            {
                get();
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

我从这样做swingworker从http下载文件并显示进度条GUI

我制作了10个progreebarswingworker实例并放入列表并像这样运行

for(ProgressBarSwingWorker p : progressList)
{
p.execute();
}

并且所有progressList都是同时开始的

我想逐步执行等待其他进度完成

所以我把像这样的done()或get()方法

for(ProgressBarSwingWorker p : progressList)
    {
    p.execute();
p.done(); // or p.get();
    }

此代码执行进度其他进度已完成

但! GUI冻结,因此我无法显示任何JLabel更改或JProgressBar

如何在没有gui冻结的情况下等待其他进度完成?

1 个答案:

答案 0 :(得分:2)

你正在尝试一些概念错误的东西。您尝试等待完成以执行另一个操作,从而产生您想要避免的单线程行为。重写代码并不重要,只要你总是试图等待你的GUI 冻结

你必须改变你的观念。而不是等待你必须告诉Swing在任务完成时该做什么,即开始下一个任务。您无需调用get,因为它与定义下一个操作无关。你可以:

  • 告诉您的ProgressBarSwingWorker对下一个的引用,并在execute方法中调用其done方法

    class ProgressBarSwingWorker extends SwingWorker<Object, Object>
    {
      ProgressBarSwingWorker next;
      // …
      public ProgressBarSwingWorker(ProgressBarSwingWorker nextWorker)
      {
        next=nextWorker;
      }
      // …
      @Override
      protected void done()
      {
        if(next!=null) next.execute();
      }
    }
    

  • 添加一个侦听器,该侦听器将调用下一个execute

    ProgressBarSwingWorker方法
    ProgressBarSwingWorker previous=null;
    for(final ProgressBarSwingWorker p: progressList)
    {
      if(previous==null) p.execute();
      else previous.addPropertyChangeListener(new PropertyChangeListener()
      {
        public void propertyChange(PropertyChangeEvent evt)
        {
          if("state".equals(evt.getPropertyName())
          && evt.getNewValue() == SwingWorker.StateValue.DONE)
            p.execute();
        }
      });
      previous=p;
    }