当前位置: 首页 > 知识库问答 >
问题:

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

岳泉
2023-03-14

我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我使用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@17java.lang.线程。状态:RUNNABLE

锁定自己的同步器:-无

"JavaFX应用程序线程"-线程t@13java.lang.线程。状态:运行在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)

锁定自己的同步器:-无

更新:我使用最新的Oracle JDK 7u17 64位LinuxFedora 16 64位。

共有3个答案

欧阳哲
2023-03-14

这是一个棘手的情况,因为(据我所知)JavaFX线程的目的是透明地利用各种硬件管道。我建议您将JavaFX请求放在一个单独的、被引用的项目中;把其他的东西,包括你的主要方法,都放在另一个地方?这对我一直都有用。

基本上,业务逻辑和模型放在一个项目中,视图和控制(通常基于JavaFX)放在另一个项目中。这允许独立终止JavaFX线程。希望这适用于你正在尝试做的事情。

昌勇锐
2023-03-14

您的主函数不属于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
    }
}
彭弘伟
2023-03-14

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

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

我通过挖掘源代码找到了答案JFXPanel有一个小片段(来自JavaFX2.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)方法永远不会做任何事情(因为firstPanelShowed==false),这会阻止监听器被删除,从而阻止JavaFX工具包关闭。。。这意味着你必须手动关闭它。

 类似资料:
  • 代码非常简单,我搜索了一下,发现我只会用到 这似乎不起作用,我也尝试过使用平台参数,比如 下面是您可以运行的测试应用程序: 锁定得可拥有同步器:-无 更新:我正在Linux Fedora 16 64bit上使用最新的Oracle JDK 7u17 64bit。

  • 我正在用场景构建器创建一个JavaFX应用程序。我在开头加了一段视频。所以我想播放视频之前,我的应用程序启动在全屏模式。问题是当它停止时,我只看到黑色尖叫,什么也没发生,我想这是因为视频是全屏的,它没有自动关闭。 我也有一个bug,在视频开始之前,我的主窗口的一些闪烁。我想这是因为视频放在控制器中,在我的应用程序启动后开始。 公共类主扩展应用程序{ 控制器类:

  • 我们为Azure Portal中托管的Web应用程序安装了应用程序Insights。

  • 我对Java FX应用程序线程有问题。下面是一个伪代码: 问题是睡眠发生在窗口中,该窗口显示在show Menu()中,show LoadingPic()根本没有显示,而在最后窗口中显示的是show Map()。 show LoadingPic中的场景有一个进度条,运行2秒,与Thread.sleep(2000)相同。 因此,似乎javafx应用程序线程块show LoadingPic()和sho

  • motioncfp.java:

  • 我通过创建固定数量的线程来使用执行器服务来进行HTTP GET数据检索。 当Tomcat停止时,我们会出现以下错误: 严重:web应用程序[/viewer]似乎已启动名为[ThreadExecutor_51616156]的线程,但未能停止该线程。这很可能会造成内存泄漏。 这是真的吗?在没有这些服务错误的情况下,如何正确停止tomcat。