我有一个程序,我在加载文件的同时显示一个窗口,通知用户文件正在加载。我决定制作一个 FileLoader 类,它是一个实际处理加载文件的 SwingWorker 和一个实现 PropertyChangeListener 的 ProgressWindow 以通知用户传递给它的 SwingWorker 的状态。
我的代码目前看起来像这样:
FileLoader loader = new FileLoader(filePath);
new ProgressWindow(loader, "Loading File", "Loading File");
//ProgressWindow's constructor calls loader.execute() inherited from SwingWorker
doc = loader.get(); //GUI Freezes when called
问题是每当我调用 loader.get() 时,它都会卡住 GUI,因此进度窗口中的进度条不会运行,整个过程毫无意义。据我所知,这是因为控制 GUI 的线程与调用 loader.get() 的线程相同,它在 loader.execute() 运行时暂停。
到目前为止,我已尝试为 loader.get() 命令或 loader.execute() 方法创建一个新线程,并在该线程上调用 SwingUtilities.invokeLater(),但随后整个程序卡住。
我考虑过为 SwingWorker.isDone() 创建一个 ChangeListener,然后运行 loader.get(),但这需要对我的代码进行一些修改,而我不想这样做。
谁能告诉我让它发挥作用的最佳方法是什么?
最佳答案
get()
与 join()
类似,它会阻塞直到被调用,并会等待 SwingWorker 完成后再被调用。错误地使用它会完全抵消最初使用 SwingWorker 的所有优势。
解决方案:在您知道 SwingWorker 已完成其处理之前,不要调用 get()
,方法是在 SwingWorker 的 done()
方法中调用它,或者,如果您需要从调用代码调用它,则在 SwingWorker 的“状态”属性为 SwingWorker.StateValue.DONE 时,在已添加到 SwingWorker 的 PropertyChangeListener 中调用它。
类似于:
final FileLoader loader = new FileLoader(filePath);
loader.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
// since DONE is enum, no need for equals(...) method
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
loader.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
});
new ProgressWindow(loader, "Loading File", "Loading File");
注意:代码未编译也未测试
编辑:添加了 try/catch。
关于java - 调用 SwingWorker.get( ) 时防止 GUI 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11547537/