将 SwingWorker
与 FileVisitor
一起使用,无法快速发布处理后的信息; GUI 挂起。我希望它没有,并且希望获得有关该问题的帮助。
以下简要概述了我如何使用 SwingWorker
和 FileVisitor
界面来搜索 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
方法中找到的每个匹配文件都会被 publish
供 SwingWorker
进行处理
。
它在大多数情况下都工作得很好,但如果有大量匹配文件,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 。
编辑
我可能找到了帮助here .
但是,哎呀,关闭??
我已经突出显示了我的问题。
最佳答案
我不知道您的问题的解决方案,但我确实知道这不应该在 SwingWorker 或其内部类中完成:
GUI.txtMaxMatches.getText())
您应该在 EDT 上获取此信息,并通过其构造函数将其传递到 SwingWorker 中。
关于java - SwingWorker 与 FileVisitor 无法快速发布处理后的信息;图形用户界面挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32123469/