JavaFX中的SecondaryLoop,如Swing?

xpu*_*mos 5 java swing javafx

我有一个Java Swing应用程序,我正在研究是否可以移植到JavaFX.该应用程序是一个内部使用的脚本语言的开发环境和模拟器.有趣的是,你可以为这种脚本语言设置断点并逐步完成它,就像任何程序员对语言的期望一样.

现在因为模拟器中的语言被解释,在解释器执行的深处,当它遇到断点时,它可以使用Java Swing SecondaryLoop类弹回到gui.因此,当命中断点时,它会调用secondaryLoop.enter().然后,gui处于活动状态,供用户检查变量并且gui组件处于活动状态.当用户在程序中点击"继续"时,它会调用secondaryLoop.exit()来继续执行解释器.解释器解开它的整个状态以回到主循环,然后在完全相同的点处从它停止的地方开始是不可行的.这就是为什么SecondaryLoop在使其工作方面具有无可估量的原因.

这在JavaFX中是否可行?

Jav*_*erJ 3

是的,这是可能的。您需要使用EnterNestedEventLoopexitNestedEventLoop方法(它们位于 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);
Run Code Online (Sandbox Code Playgroud)

现在,在使用它之前,请注意件重要的事情

  1. com.sun.javafx.tk.Toolkit类不是公共 API 的一部分,因此 Oracle 保留删除它的权利,恕不另行通知从 Java 7 到 8u51,我一直很好地使用它,因此它们可以永远留在那里,更改包/名称或完全消失(不太可能)。

  2. 嵌套循环(以及 Swing 的辅助循环)非常适合灵活性和小型应用程序,但过度使用它们通常会付出代价。嵌套到许多循环(巨大的堆栈跟踪)通常会在应用程序中导致“奇怪”的行为,因为代码的初始部分可能最终会等待与它们完全无关的四到五个事情。我见过 FX 嵌套循环在 FX WebEngineexecuteScript() 调用中导致“空”异常,以及重复键盘预处理(当配对 FX+Swing 时)等问题。

也就是说,我建议使用javafx.concurrent.Task(如果有意义的话)。使用 Task 类需要更多的努力,但我认为这是正确的做事方式,并且可能会节省您大量的维护时间。

有关 FX Task 类的额外参考,请参阅这篇精彩文章:http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm

更新:enterNestedEventLoopexitNestedEventLoop将成为Java 9公共 API(平台类)的一部分,更多信息请参见JDK-8090865

希望这可以帮助!