如何停止“JavaFX应用程序线程”

我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我正在使用JavaFx框架(我需要一些函数,如文本的CSS样式)我只是生成一些形状和文本到隐藏的场景然后保存那些存档的,就是这样,

我知道要使用JavaFx我必须将图形操作传递给JavaFx线程,但是当一切都完成后我必须关闭应用程序(几个小时后),这个JavaFx线程仍然保持打开…我真的不想强制退出System.exit(),因为如果有什么东西被阻止我可能想知道/等待(我也不想将所有内容都作为JavaFx应用程序执行(因为JavaFx组件不到我主应用程序的1%)

代码很简单,谷歌搜索我发现只使用

Platform.exit(); 

这似乎不起作用,我也试过玩平台参数,如

 Platform.setImplicitExit(false); 

这是我可以运行的测试应用程序:

 import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.geometry.Pos; import javafx.scene.layout.VBox; public class SOTestFX { public static void main(String[] args) { SOTestFX t = new SOTestFX(); t.runFxThread(); } public void runFxThread(){ //Application.launch(args); final JFXPanel jfxPanel = new JFXPanel(); Platform.runLater(new Runnable() { @Override public void run() { System.err.println("CREATING IMAGE"); simpleFXoperations(); System.err.println("NOW CALL EXIT"); System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW"); Platform.exit(); } }); try { Thread.sleep(3000); // just wait a bit if something should happen, let it happen.. } catch (InterruptedException e) { e.printStackTrace(); } //jfxPanel.removeNotify(); // return -> java.lang.NullPointerException //Platform.exit(); // -> does nothing System.err.println("i will never die!"); } public void simpleFXoperations(){ VBox vbox1 = new VBox(); vbox1.setAlignment(Pos.BOTTOM_CENTER); vbox1.setStyle("-fx-border-style: solid;" + "-fx-border-width: 1;" + "-fx-border-color: white"); System.err.println("simpleFXoperations() _DONE"); } } 

这是永不关闭的线索

“附加侦听器” – 线程t @ 17 java.lang.Thread.State:RUNNABLE

锁定的可拥有同步器: – 无

“JavaFX应用程序线程” – 线程t @ 13 java.lang.Thread.State:RUNNABLE,位于com.sun.glass.ui.gtk.GtkApplication._runLoop(本地方法),位于com.sun.glass.ui.gtk.GtkApplication $ 3 $ 1.run(GtkApplication.java:82)在java.lang.Thread.run(Thread.java:722)

锁定的可拥有同步器: – 无

更新:我在Linux Fedora 16 64bit上使用最新的Oracle JDK 7u17 64位。

固定:

我能够通过在Platform.exit()之前调用com.sun.javafx.application.PlatformImpl.tkExit()来解决这个问题。 我不太了解JavaFX源,但它似乎正在工作; 因人而异。

更新:在Java 8中执行此操作将产生警告,您可以使用@SuppressWarnings("restriction")关闭警告。 这应该不是问题。

说明:

我通过挖掘源代码来解决这个问题; JFXPanel有这个小片段(来自JavaFX 2.2.25)

 finishListener = new PlatformImpl.FinishListener() { public void idle(boolean paramAnonymousBoolean) { if (!JFXPanel.firstPanelShown) { return; } PlatformImpl.removeListener(JFXPanel.finishListener); JFXPanel.access$102(null); if (paramAnonymousBoolean) Platform.exit(); } public void exitCalled() { } 

问题是,如果你在你的应用程序中只使用了一点点JavaFX,那么idle(boolean)方法永远不会做任何事情(因为firstPanelShown == false ),这会阻止侦听器被删除,这会阻止JavaFX Toolkit关闭…这意味着你必须手动关闭它。

您的main函数不属于JavaFx Application对象,我认为您的程序永远不会执行应用程序线程循环。

看来你应该这样做:

 public class SOTestFX extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { // Do stuff here to show your stage or whatever you want; // This will be called on the JavaFX thread } } 

这是一个很滑的情况,因为(据我的理解),JavaFX线程的目的是透明地利用各种硬件管道。 我建议你将JavaFX请求放在一个单独的引用项目中; 并将其他所有内容(包括主要方法)保留在另一个中? 这对我来说总是有用的。

基本上,业务逻辑和模型在一个项目中进行,而查看和控制(通常基于JavaFX)在另一个项目中。 这允许独立终止JavaFX线程。 希望这适用于您要做的事情。

我在这方面做了很多尝试,因为上述答案都不适合我。 对我来说最好的事情就是关闭整个JVM

 System.exit(1); 

因为我的整个应用程序只是一个JavaFX应用程序,因此关闭舞台时可以关闭它。 在我的情况下,1只是一个随机的int。