我有一个Java Swing应用程序,我正在研究是否可以移植到JavaFX。该应用程序是一个内部使用的脚本语言的开发环境和模拟器。有趣的是,您可以为这种脚本语言设置断点并逐步完成它,就像任何程序员对语言的期望一样。
现在因为模拟器中的语言被解释,在解释器执行的深处,当它遇到断点时,它可以使用Java Swing SecondaryLoop类弹回到gui。因此,当命中断点时,它会调用secondaryLoop.enter()。然后,gui处于活动状态,供用户检查变量并且gui组件处于活动状态。当用户在程序中点击“继续”时,它会调用secondaryLoop.exit()来继续执行解释器。解释器解开它的整个状态以回到主循环,然后在完全相同的点处从中断的地方开始是不可行的。这就是为什么SecondaryLoop在使其工作方面非常宝贵。
这可以在JavaFX中使用吗?
答案 0 :(得分:2)
是的,这是可能的。您需要使用 enterNestedEventLoop 和 exitNestedEventLoop 方法(它们位于com.sun.javafx.tk.Toolkit类中)。请参阅此用法示例:
// Make sure to import the FX Toolkit first
import com.sun.javafx.tk.Toolkit;
// This object will be used as a unique identifier to the nested loop (to
// block the execution of the thread until exitNestedEventLoop is called)
final Object loopLock = new Object();
// Simulate a long process thread (DB call, download, etc)
Thread longProcess = new Thread(new Runnable()
{
@Override
public void run()
{
// Sleep for 12 seconds to simulate a long process
try
{
Thread.sleep(12000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
// Setup a result to pass back to the enterNestedLoop() caller
String result = "Result of this long process";
// We are now done. Call exitNestedEventLoop() to unblock
// the enterNestedLoop() caller. This needs to run from
// the FX Thread so use Platform.runLater()
Runnable fxRunner = new Runnable()
{
public void run()
{
try
{
Toolkit.getToolkit().exitNestedEventLoop(loopLock,
result);
} catch (Throwable t)
{
t.printStackTrace();
}
}
};
Platform.runLater(fxRunner);
}
});
// Start that long process from the FX Thread
longProcess.start();
// The next call will block until exitNestedEventLoop is called, however
// the FX Thread will continue processing UI requests
Object result = Toolkit.getToolkit().enterNestedEventLoop(loopLock);
// Next statement will print: "Result of this long process"
System.out.println("Result is: " + result);
现在,在您使用警告之前两件重要的事情:
com.sun.javafx.tk.Toolkit 类不属于公共API,因此Oracle保留删除它的权利,恕不另行通知。我从Java 7到8u51一直使用它很好,所以他们可以永远呆在那里,更改包/名称或完全消失(不太可能)。
嵌套循环(以及Swing的辅助循环)非常适合灵活性和小型应用程序,但过度使用它们通常需要付出代价。嵌套到许多循环(巨大的堆栈跟踪)通常会导致"奇怪的"应用程序中的行为,因为代码的初始部分可能最终会等待与它们完全无关的四到五件事情。我已经看到FX嵌套循环导致"空" FX WebEngine中的异常执行executeScript()调用和复制键盘预处理(当配对FX + Swing时)等问题。
那就是说我会建议使用 javafx.concurrent.Task (如果有意义的话)。使用Task类需要更多的努力,但我认为这是正确的做事方式,可能会为您节省大量的维护时间。
有关FX Task课程的额外参考,请参阅这篇精彩的文章:http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm
更新: enterNestedEventLoop 和 exitNestedEventLoop 将成为 Java 9 公共API(平台类)的一部分,{{3}中的更多信息}
希望这有帮助!