java - SwingWorker 与 FileVisitor 无法快速发布处理后的信息;图形用户界面挂起

标签 java swing swingworker filevisitor

SwingWorkerFileVisitor 一起使用,无法快速发布处理后的信息; GUI 挂起。我希望它没有,并且希望获得有关该问题的帮助

以下简要概述了我如何使用 SwingWorkerFileVisitor 界面来搜索 Windows 目录节点以查找与用户指定条件匹配的文件。 :

  public class Main 
  {
    public static void main(String args[]) 
    {
      EventQueue.invokeLater( new Runnable() {
          @Override public void run() {
            gui = new GUI();
          }});
    }
  }
  //==============================================================
  public class GUI extends JFrame
  {
    public     GUI()
    {
      init();
      createAndShowGUI();
    }

     private void init()
     {
       dftTableModel = new DefaultTableModel(0 , 4);
         tblOutput     = new JTable(dftTableModel);
         tblOutput.setAutoResizeMode(AUTO_RESIZE_OFF);
         scrTblOutput     = new JScrollPane(tblOutput);
       dftTableModel.setColumnIdentifiers(new Object[]{"Date", "Size", "Filename", "Path"});

编辑如果我只包含这两行,问题可能会立即得到解决

       tca = new tablecolumnadjuster.TableColumnAdjuster(tblOutput);
       tca.setDynamicAdjustment(true);

     }

      private static void btnSearchActionPerformed(ActionEvent evt) 
      {
        TASK task = new TASK();
        task.execute();      
      }
    }
  }
  //==============================================================

  public class TASK extends SwingWorker<Void,String>
  {

    private class rowRec{
      String date;
      int size;
      String filename;
      String pathname;

      private rowRec(String d, int s, String f, String p) 
      {
        date = d; 
        size = s; 
        filename = f; 
        pathname = p;
      }
    }

    FV fv;

    TASK() {        fv = new FV();        }

    //-------------- inner class   

      class FV implements FileVisitor<Path>
      {
        // When walk begins, internal FileVisitor code makes this routine
        // loop until no more files are found OR disposition = TERMINATE.

        public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException 
        {
          if(f.getFileName().toString().toLowerCase().matches(fPatt.toLowerCase().trim()))
          {

             publish(s); 

             if(++k > parseInt(GUI.txtMaxMatches.getText()))

                disposition = TERMINATE;
                publish("Stopped at max. records specified");
          }
          return disposition;
        }
      }
    //----------------

    private  void report(String s)
    {
      rowData = new rowRec(date, isize, filename, path);
      dftTableModel.addRow(new Object[]{rowData.date, rowData.size, rowData.filename, rowData.pathname});
    }

    @Override
    protected void process(List<String> chunks)
    {
      chunks.stream().
        forEach
        (
           (chunk) -> 
           {
             report(chunk);
           }
      );
      kc += chunks.size();
      System.out.println(kc); // *********************************
    }

    @Override
    public Void doInBackground() throws Exception 
    {
        disposition = FileVisitResult.CONTINUE;
        Files.walkFileTree(GUI.p ,fv);
    }
  }

GUI 启动 SwingWorker 的新实例,其工作是显示(在 JTable 中)由 实例找到的文件信息code>TASK 它启动。 TASK 实例化 FileVisitor,并且 walkFileTree 开始。 visitFile 方法中找到的每个匹配文件都会被 publishSwingWorker 进行处理

它在大多数情况下都工作得很好,但如果有大量匹配文件,GUI 将变得无响应几秒钟;同时,发生了大量的读取和显示,并且每读取数千个文件就会更新 UI。

尽管使用 SwingWorker 在后台填充 JTable,显然(我猜测)太多的匹配文件信息来得太快而无法跟上。

这就是我这么说的原因:

尽管 visitFile 有一个计数器向 TERMINATE 发出信号,process 显然在向 JTable 添加记录方面远远落后于 process/。其中的 println 显示,随着时间的推移,传递的 block 数量变化很大,具体取决于 FileVisitor 查找匹配的速率:

41
81
138
250
604
1146
...
1417
1497
1590
1670
1672
1676
1680
1682
1692
1730
1788
1794
1797
1801
1807
1820
1826
1829
1847
1933
2168
10001

visitFile 终止后,process 必须向 JTable 发送 (10001-2168) 或 7833 条记录,并且花费了很长时间时间,GUI 在大部分时间都没有响应。事实上,如果最大。匹配数是(荒谬的)10,000,程序挂起很长时间,但是 JTable 中有 10,000 条记录。

我不知道如何处理无响应的情况。我希望能够点击“停止”按钮并让程序停止。或者能够X(关闭)窗口。没办法。

我没有正确使用 SwingWorker 吗? 我无法使树遍历基于 SwingWorker 因为我没有循环我可以使用(它是内部的)。

附注虽然明显挂起,但 javaw 占用了 25% 的 CPU 时间,并且随着 process 的缓慢进行,每秒增加其内存分配约 16K,直到它最终发布最后一个 block 。

enter image description here

编辑

我可能找到了帮助here .

但是,哎呀,关闭??

我已经突出显示了我的问题。

最佳答案

我不知道您的问题的解决方案,但我确实知道这不应该在 SwingWorker 或其内部类中完成:

GUI.txtMaxMatches.getText())

您应该在 EDT 上获取此信息,并通过其构造函数将其传递到 SwingWorker 中。

关于java - SwingWorker 与 FileVisitor 无法快速发布处理后的信息;图形用户界面挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32123469/

相关文章:

java - java程序中的命令提示符

java - 使用解析的信息填充 JTable

java - JFrame 上的 Enter 键

java - 使用 Java Swing 进行线程处理

java - 如何使 jButton 操作不仅仅在一次运行中起作用?

java - while block 中的初始化?

java - JTabbedPane 中具有相等(恒定)宽度的选项卡

java - ProcessBuilder 的命令有限制吗?

java - SwingWorker 上的异常不可捕获

java - 输出在 Java 循环的开始和结束时出现偏差