使用不快速发布处理过的信息SwingWorker
;GUI 挂起。我宁愿它没有,也想帮助解决这个问题。FileVisitor
以下是我如何使用接口在 Windows 目录节点中搜索与用户指定条件匹配的文件的简要SwingWorker
概述FileVisitor
。:
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
的实例找到的文件信息。实例化, 并开始。在方法中找到的每个匹配文件都被编辑为to 。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
必须发送(10001-2168)或 7833 条记录到JTable
,并且花费了很长时间,并且 GUI 大部分时间都没有响应。事实上,如果最大。匹配是(荒谬的)10,000,程序挂起很多分钟,但 10,000 条记录在JTable
.
我不知道如何处理反应迟钝。我希望能够按下停止按钮并停止程序。或者能够X
(关闭)窗口。没门。
我没有SwingWorker
正确使用吗?SwingWorker
由于没有可用的循环(它是内部的),因此我无法基于树行走。
PS 虽然显然挂起,但javaw
它占用了稳定的 25% 的 CPU 时间,并将其内存分配增加了大约 16K/秒,process
直到它最终发布最后一个块。
编辑
我可能在这里找到了帮助。
但是,天哪,接近??
我已经强调了我的问题。