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

2022-09-03 00:45:46

我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我使用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");
    }
}

这是从不关闭的线程

“Attach Listener” - Thread t@17 java.lang.Thread.State: RUNNABLE

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

“JavaFX Application Thread” - Thread t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) at java.lang.Thread.run(Thread.java:722)

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

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


答案 1

修复:

我能够通过在之前立即致电来解决此问题。我不太了解JavaFX源代码,但它似乎正在工作;新浪网.com.sun.javafx.application.PlatformImpl.tkExit()Platform.exit()

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

解释:

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

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,那么该方法永远不会做任何事情(因为),这可以防止侦听器被删除,从而防止JavaFX关闭...这意味着您必须手动关闭它。idle(boolean)firstPanelShown == falseToolkit


答案 2

您的主要函数不属于JavaFx应用程序对象,我认为您的程序永远不会产生应用程序线程循环。

看来你应该这样做:

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
    }
}

推荐