【问题标题】:gui frozen when calling SwingWorker method get() [duplicate]调用 SwingWorker 方法 get() 时 gui 冻结 [重复]
【发布时间】:2014-01-31 13:03:32
【问题描述】:
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 冻结的情况下等待其他进度完成?

【问题讨论】:

  • @GeeHad 我在您的链接中使用了代码,但它也不起作用我在线程中附加我的代码我错了吗?
  • “如何在没有 gui 冻结的情况下等待其他进度完成?”这简直是​​个错误的问题。在 GUI 线程中等待意味着冻结 GUI。 不要在 GUI 线程内等待.
  • @Holger hmm... 以及如何知道 GUI SwingWorker 线程已完成?我要一个一个下载文件

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


【解决方案1】:

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

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

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

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

  • 添加一个监听器,它将调用下一个ProgressBarSwingWorkerexecute 方法

    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;
    }
    

【讨论】:

  • 它工作正常!!谢谢我整天都在寻找答案:(非常感谢!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 2015-09-20
  • 2021-05-03
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 2018-01-05
相关资源
最近更新 更多