我有一个定制的 JFileChooser
它的approveSelection() 方法稍作修改:
public void approveSelection()
{
File file = getSelectedFile();
changeGui();
final Object a = makeALongCalcualtion(file);
if (a != null)
{
super.approveSelection();
SwingWorker<Document, Void> open = new SwingWorker<Document, Void>()
{
@Override
protected Document doInBackground() throws Exception
{
return createADocument(a);
}
@Override
protected void done()
{
try
{
if(get() != null)
{
changeGui();
}
else
{
//TODO error message
changeGui();
}
}
catch (InterruptedException | ExecutionException e)
{
//TODO error message
changeGui();
}
}
};
open.execute();
}
else
{
//TODO error message
changeGui();
}
}
changeGui() 方法将 JProgressBar 设置为不确定并使用新字符串更新 JLabel。
如果提供给 makeALongCalcualtion(file) 的文件类型无效,它将返回 null,否则返回传递给 SwingWorker 的信息,SwingWorker 可以使用它在程序中实际创建文件的表示(文档对象)。
但是,这不起作用,因为 makeALongCalcualtion(file) 没有在 SwingWorker 方法中调用,这会阻塞 EDT。
为了解决这个问题,我必须在 SwingWorker 中调用 makeALongCalcualtion(file)。我可以毫无问题地将那部分代码移入 SwingWorker,但随后我将不得不(由于我的代码逻辑)将 super.approveSelection() 一起移动。
所以底线是,对于这种特定情况,我如何从 doInBackground() 中调用 super.approveSelection() ?
//更多信息
应该发生什么:
- 用户选择并打开文件
- JLabel 和 JProgressBar 更新,不确定进度开始播放。
- 如果 makeALongCalcualtion(file) return null 用户会收到错误窗口警告,但 JFileChooser 会打开,从而可以在错误窗口关闭时再次选择。
- 否则,调用 super.approveSelection(),允许选择器关闭。
- 创建了一个文档(但如果出现问题,创建文档的方法返回 null)。
- 如果一切正常,JLabel 会更新,progressBar 动画会停止(indeterminate 设置为 false)。
- 如果出现问题,则与步骤 6 中的情况相同,只是 JLabel 中的消息不同。
发生什么了:
- 相同的
- 相同的
- 一样,但是当 makeALongCalculation(file); 开始,progressBar 冻结。
- 相同的
- 相同的
- 相同,但动画没有停止(因为进度条被冻结),只有冻结的“图片”被删除,进度条返回到之前的状态。
- 相同的
编辑
我对我的程序做了一些改动,现在我有了这个:
批准选择():
public void approveSelection()
{
File file = getSelectedFile();
Main.getStatusBar().startOpen();
final WorkOpen open = new WorkOpen(file);
open.execute();
open.addPropertyChangeListener(new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
if (evt.getNewValue().equals("DONE"))
{
if (open.failed())
{
//TODO error message
Main.getStatusBar().endOpen(false);
}
else
{
Main.getStatusBar().endOpen(true);
}
}
}
}
});
}
摇摆工人:
class WorkOpen extends SwingWorker<Document, Void>
{
boolean failed = false;
File file;
public boolean failed()
{
return failed;
}
@Override
protected Document doInBackground() throws Exception
{
ArrayList<String> data = Opener.extractData(file);
if (data != null)
{
//My little path/name/similar managing system
FileComplex fullPath = new FileComplex(file.toString());
return Opener.createDocument(fullPath.getFullName(), fullPath.getFullPath(), data);
}
else
{
failed = true;
return null;
}
}
@Override
protected void done()
{
try
{
if(get() != null)
{
Main.addDocument(get());
}
}
catch (InterruptedException | ExecutionException e)
{
failed = true;
}
}
WorkOpen(File file)
{
this.file = file;
}
}
现在的问题是在哪里调用 super.approveSelection()。它必须等待工作人员完成执行,但我无法从属性更改侦听器中调用它。
在这里做什么?
编辑 2
正如 HovercraftFullOfEels 建议的那样,我修复了我的代码并编译并运行。但是 JProgressBar 冻结的问题仍然存在。另外,我不得不介绍一些我不知道是否应该拥有的东西:
private void superApproveSelection()
{
super.approveSelection();
}
public void approveSelection()
{
final File file = getSelectedFile();
class OpenWorker extends SwingWorker<Boolean, Void>
{
Document document;
Document getDocument()
{
return document;
}
@Override
protected Boolean doInBackground() throws Exception
{
ArrayList<String> data = Opener.extractData(file);
if (data != null)
{
//I had to start the progressBar here, because if invalid
//file was selected (extractData(file) returns null if it was),
//nothing should happen (maybe an error
//window later, handled with a new Runnable() same as this:
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
Main.getStatusBar().startOpen();
}
});
FileComplex fullPath = new FileComplex(file.toString());
document = Opener.createDocument(fullPath.getFullName(), fullPath.getFullPath(), data);
return true;
}
else
{
return false;
}
}
};
final OpenWorker opener = new OpenWorker();
opener.addPropertyChangeListener(new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if ("state".equals(evt.getPropertyName()))
{
if (evt.getNewValue() == SwingWorker.StateValue.DONE)
{
if(opener.getDocument() != null)
{
superApproveSelection();
Main.addDocument(opener.getDocument());
Main.getStatusBar().endOpen(true);
}
else
{
try
{
//I'm retrieveing doInBackground()'s value to see if
//progressBar needs stoping (it also displays some
//text, so it must not be called unless the
//progressBar was started).
if (opener.get())
{
Main.getStatusBar().endOpen(false);
}
}
catch (InterruptedException | ExecutionException e)
{
//TODO error something went wrong
}
}
}
}
}
});
opener.execute();
}