使用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
实例找到的TASK
文件信息。 TASK
实例化FileVisitor
,walkFileTree
开始。 visitFile
方法中找到的每个匹配文件publish
为SwingWorker
至process
。
它在大多数情况下都很有效,但是如果有大量匹配的文件,GUI会在几秒钟内无响应;同时,已经发生了大量的阅读和显示,并且每隔几千个文件读取就会更新UI。
尽管在背景中使用SwingWorker
来填充JTable
,显然(我猜是)太多匹配的文件信息来得太快而无法跟上。
这就是我说的原因:
即使visitFile
有一个向TERMINATE
发出信号的计数器,但process
显然远远落后于向JTable
添加记录。其中的println
表示,随着时间的推移,chunks
传递的数量会有很大差异,具体取决于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,该程序挂起很多MINUTES,但是JTable
中有10,000个记录。
我不知道如何处理无响应。我希望能够点击STOP按钮让程序停止。或者能够X
(关闭)窗口。没办法。
我没有正确使用SwingWorker
吗?我无法让树步行基于SwingWorker
,因为我没有可用的循环(它是内部的) )。
P.S。虽然显然是挂起的,javaw
占用了25%的CPU时间并且每秒增加大约16K的内存分配,因为process
一直在下去,直到它最终发布最后一个块。
修改
我可能找到了帮助here。
但是,gee, 关闭 ??
我突出了我的问题。
答案 0 :(得分:2)
我不知道你的问题的解决方案,但我知道这不应该在SwingWorker或其内部类中完成:
GUI.txtMaxMatches.getText())
您应该在EDT上获取此信息,并通过其构造函数将其传递给SwingWorker。
答案 1 :(得分:0)
响应问题在一行代码中得到解决。
// tca.setDynamicAdjustment(true);
请参阅原始问题中的编辑。