【发布时间】:2017-08-11 12:20:21
【问题描述】:
我试图在 SO 上找到我的问题的答案,但由于它们的丰富性和多样性,我有些困惑。这是我的问题:我的应用程序比较两个文件并在Swing.JTextPane 中打印出结果。我用一个按钮调用处理文件的代码,为了避免挂起 UI,我用SwingWorker 处理每对文件。这是它的代码:
class ProcessAndPrintTask extends SwingWorker<Void, Void> {
private Report report;
Integer reportResult;
ProcessAndPrintTask(Report report) {
this.report = report;
reportResult = null;
}
@Override
protected Void doInBackground() {
try {
reportResult = report.getComparator().compareTwoFiles(new FileInputStream(new File(pathToReportsA + report.getFilename())),
new FileInputStream(new File(pathToReportsB + report.getFilename())));
}
catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
@Override
protected void done() {
String message = report.getFilename() + ": ";
if (reportResult != null) {
switch (reportResult) {
case 1:
StyleConstants.setBackground(style, Color.GREEN);
try {
doc.insertString(doc.getLength(), message + "MATCH\n", style);
}
catch (BadLocationException ex) {ex.printStackTrace();}
break;
case 0:
StyleConstants.setBackground(style, Color.RED);
try {
doc.insertString(doc.getLength(), message + "NO MATCH\n\n", style);
try {
for (String s : report.getComparator().getDifferences(
new FileInputStream(new File(pathToReportsA + report.getFilename())),
new FileInputStream(new File(pathToReportsB + report.getFilename())))) {
doc.insertString(doc.getLength(), s + "\n", style);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
catch (BadLocationException ex) {ex.printStackTrace();}
break;
case -1:
StyleConstants.setBackground(style, Color.CYAN);
try {
doc.insertString(doc.getLength(), message + "BOTH FILES EMPTY\n", style);
}
catch (BadLocationException ex) {ex.printStackTrace();}
break;
default:
StyleConstants.setBackground(style, Color.ORANGE);
try {
doc.insertString(doc.getLength(), message + "PROBLEM\n", style);
}
catch (BadLocationException ex) {ex.printStackTrace();}
}
}
else {
StyleConstants.setBackground(style, Color.ORANGE);
try {
doc.insertString(doc.getLength(), message + "FILE OR FILES NOT FOUND\n", style);
}
catch (BadLocationException ex) {ex.printStackTrace();}
}
}
}
doInBackground() 进行比较,done() 根据比较结果格式化消息并打印出来。问题是程序不会等到处理并打印一对,因此结果不会按照打开的顺序打印,这可能会让用户感到非常困惑:大多数文件都很小而且真的过去了很快,因此比较似乎在某个时候完成,但仍有更大的文件正在处理。
我读到了使用PropertyChangeListener 的可能性,但我看不出它与使用done() 方法有何不同...我尝试在doInBackground() 中进行比较和打印,但这会弄乱格式(这是意料之中的——在打印完成之前,背景颜色会改变)。我还尝试在调用SwingWorker 的循环内任意时间调用Thread.sleep(),如下所示:
try (FileInputStream reportListExcelFile = new FileInputStream(new File(reportListPath))) {
Workbook workbook = new XSSFWorkbook(reportListExcelFile);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> iter = sheet.iterator();
// skip first row that contains columns names
iter.next();
while (iter.hasNext()) {
try {Thread.sleep(1000);} catch (Exception ex) {ex.printStackTrace();}
Row r = iter.next();
String name = r.getCell(0).getStringCellValue();
String format = r.getCell(1).getStringCellValue();
Report currentReport = new Report(name, format);
new ProcessAndPrintTask(currentReport).execute();
}
}
它不仅看起来像一个丑陋的拐杖,而且还导致 GUI 挂起,直到所有文件对都被比较。
有解决办法吗?
【问题讨论】:
-
您只需要从第一个的
done方法开始您的第二个SwingWorker您也可以只使用一个SwingWorker并在一个doInBackground方法中启动两个任务。 -
但是我必须将
Report的集合传递给SwingWorker,然后在worker 内部进行迭代,对吗? -
试过了,效果很好——谢谢!
标签: java multithreading swing concurrency swingworker