作为问题的后续问题" JavaFX FileChooser in swing",我已经回答了,我想知道是否有可能在Swing中模拟模态阻塞调用优雅的方式。这是相关代码:
// a trick to emulate modality:
final JDialog modalBlocker = new JDialog();
modalBlocker.setModal(true);
modalBlocker.setUndecorated(true);
modalBlocker.setOpacity(0.0f);
final CountDownLatch modalityLatch = new CountDownLatch(1);
final FutureTask<T> task = new FutureTask<T>(() -> {
// <-- some code checking whether the task is cancelled
// and notifying that it is started
try {
return callable.call();
} finally {
// Wait until the Swing thread is blocked in setVisible():
modalityLatch.await();
// and unblock it:
SwingUtilities.invokeLater(()
-> modalBlocker.setVisible(false));
}
});
// run the task in the JavaFX thread:
Platform.runLater(task);
// <-- some code waiting until the task is started,
// canceling it if it's not
// A trick to notify the task AFTER we have been blocked
// in setVisible():
SwingUtilities.invokeLater(() -> {
// notify that we are ready to get the result:
modalityLatch.countDown();
});
modalBlocker.setVisible(true); // blocks
modalBlocker.dispose(); // release resources
try {
return task.get();
} catch (ExecutionException ex) {
// exception handling
}
这里的想法是在阻止用户输入的同时保持Swing更新,重新绘制,移动进度条和执行其他可视任务,直到阻塞调用返回。如果我做了一个简单的return task.get()
没有所有这种模态混乱,那么Swing会在任务工作时冻结,这不是灾难性的,但仍然是不可取的。
我试图查看JDialog / Dialog源代码来弄清楚模态是如何在没有完全冻结GUI的情况下阻塞的,但是唉,代码非常复杂,更糟糕的是,使用太多的私有功能会阻止我这样做在我的代码中,即使我弄清楚它是如何工作的。
问题是:也许有一种更优雅的方式来做我错过的事情?我只需要执行一个阻止调用来保持GUI更新,但阻止所有用户输入,直到调用返回。