当前位置: 首页 > 面试题库 >

防止在调用SwingWorker.get()时冻结GUI

羊舌阎宝
2023-03-14
问题内容

我有一个程序在其中加载文件,同时显示一个窗口以通知用户正在加载文件。我决定制作一个FileLoader类,它是一个实际上处理了文件加载的SwingWorker类,以及一个实现PropertyChangeListener的ProgressWindow,用于通知用户传递给它的SwingWorker的状态。

我的代码当前如下所示:

FileLoader loader = new FileLoader(filePath);
new ProgressWindow(loader, "Loading File", "Loading File");
//ProgressWindow's constructor calls loader.execute() inherited from SwingWorker
doc = loader.get(); //GUI Freezes when called

问题是,每当我调用loader.get()时,它都会冻结GUI,因此“进度窗口”中的进度栏​​不会运行,并且整个过程毫无意义。据我所知,这是因为控制GUI的线程与调用loader.get()的线程相同,而该线程在loader.execute()运行时保持不变。

到目前为止,我尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在该线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。

我已经考虑过为SwingWorker.isDone()创建一个ChangeListener,然后运行loader.get(),但这将需要对我的代码进行一些重做,而我不希望这样做。

谁能告诉我最好的方法是使它起作用?


问题答案:

get()就像join()它会一直阻塞直到被调用一样,并且会等待SwingWorker完成之后才被调用。错误地使用它可以完全抵消使用SwingWorker的所有优势。

解决方案:在get()知道SwingWorker已完成处理之前,不要调用它,done()方法是在SwingWorker的方法中调用它,或者如果需要从调用代码中调用它,则在已添加到SwingWorker的PropertyChangeListener中当SwingWorker的“状态”属性为SwingWorker.StateValue.DONE时。

就像是:

  final FileLoader loader = new FileLoader(filePath);

  loader.addPropertyChangeListener(new PropertyChangeListener() {
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        if ("state".equals(evt.getPropertyName())) {
           // since DONE is enum, no need for equals(...) method
           if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
              try {
                 loader.get();
              } catch (InterruptedException e) {
                 e.printStackTrace();
              } catch (ExecutionException e) {
                 e.printStackTrace();
              }
           }
        }
     }
  });

  new ProgressWindow(loader, "Loading File", "Loading File");

注意:未经编译或测试的代码

编辑:尝试/捕获添加。



 类似资料:
  • 我有一个带有“开始”按钮和进度条的小型GUI测试。期望的行为是: 单击开始 Progressbar振荡5秒 进度条停止 观察到的行为是“开始”按钮冻结5秒钟,然后显示进度条(无振荡)。 以下是我目前的代码: 根据Bryan Oakley提供的信息,我知道我需要使用线程。我试着创建一个线程,但我猜,由于线程是从主线程中开始的,所以没有帮助。 我的想法是将逻辑部分放在一个不同的类中,并从该类中实例化G

  • 问题内容: 我有一个带有“开始”按钮和进度条的小型GUI测试。所需的行为是: 点击开始 进度条振荡5秒钟 进度栏停止 观察到的行为是“开始”按钮冻结5秒钟,然后显示进度条(无振荡)。 到目前为止,这是我的代码: 根据Bryan Oakley 在此提供的信息,我了解我需要使用线程。我尝试创建一个线程,但是我猜测由于该线程是从主线程中启动的,因此没有帮助。 我有想法放置在不同的类中的逻辑部分,以及从该

  • 问题内容: 好像我使用加载动态内容,结果缓存在浏览器中。 在QueryString中添加一些随机字符串似乎可以解决此问题(我使用),但这听起来像是一种hack。 还有其他方法可以做到这一点吗?或者,如果唯一字符串是实现此目标的唯一方法,则除之外还有其他建议吗? 问题答案: 我使用,这将避免冲突,除非您在同一毫秒内发生多个请求: 编辑: 这个答案已经好几年了。它仍然有效(因此我没有删除它),但是 现

  • 我有一个有3个选项卡的ViewPager。根据我所看到的情况,当容器活动开始时,前两个片段将处于恢复状态。我还注意到,只有并排的两个片段被恢复,第三个被停止。我遇到的问题是,我从网络加载数据用于第一个片段,并将自定义对象存储在一个ArrayList中,这很正常,但当我导航到第三个片段时,数据会随着第一个片段进入停止状态而丢失。因此,当从第三个片段导航回第一个片段时,ArrayList就会为空(我在

  • 问题内容: 我有一个非常小的.so文件(可在此处找到:https ://docs.google.com/leaf?id=0B4MxFm- ACB3INjhkMjhlNzktYzkxYy00Zjk5LTk0Y2MtZDE2MWQ2MzY1OWUy &hl=zh_CN& authkey =CMrJguwN) 我试图将其加载到RHEL上的Java中,而Java 只是冻结(没有错误或异常)。我在LD_LI

  • 我知道有很多关于这个话题的问题,但我还是找不到一个解决办法。 我有一个应用程序,可以加载和显示图像(就像智能手机上的常规图库应用程序一样) 我加载了背景中的所有图像与协同线-在这个过程的这个阶段没有问题。 当我通知适配器有关数据时就会出现问题。notifyDataSetChanged()调用会冻结UI一段时间。 我们讨论的是相对较大的网格(例如1000+张照片) 其他线程中的几乎所有答案都建议,我