web-dev-qa-db-ja.com

「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:com.Sun.glass.ui.gtk.GtkApplication._runLoop(ネイティブメソッド)で実行可能com.Sun.glass.ui.gtk.GtkApplication $ 3 Java.lang.Thread.run(Thread.Java:722)で$ 1.run(GtkApplication.Java:82)

ロックされた所有可能なシンクロナイザー:-なし

更新: Linux Fedora 1664ビットで最新のOracleJDK 7u1764ビットを使用しています。

17
Francesco

修正:

com.Sun.javafx.application.PlatformImpl.tkExit()の直前にPlatform.exit()を呼び出すことで、この問題を修正することができました。私はJavaFXソースをあまりよく理解していませんが、機能しているようです。 YMMV。

pdate: 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のシャットダウン...つまり、手動でシャットダウンする必要があります。

25
durron597

(私の理解では)JavaFXスレッドの目的は、さまざまなハードウェアパイプラインを透過的に利用することであるため、これは滑りやすい状況です。 JavaFXリクエストを別の参照されたプロジェクトに配置することをお勧めします。メインメソッドを含む他のすべてを別のメソッドに保持しますか?それはいつも私のために働いています。

基本的に、ビジネスロジックとモデルは一方のプロジェクトに組み込まれ、ビューと制御(通常はJavaFXベース)はもう一方のプロジェクトに組み込まれます。これにより、JavaFXスレッドを独立して終了できます。うまくいけば、それはあなたがやろうとしていることに当てはまります。

2
Michael Oberlin

あなたのメイン関数は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
    }
}
2
LeonidVlad

上記の答えはどれもうまくいかなかったので、私はこれについて多くのことを試みました。私にとって最良のことは、JVM全体を使用してシャットダウンすることでした

System.exit(1);

私のアプリケーション全体は1つのJavaFXアプリケーションであるため、ステージを閉じるときにシャットダウンできます。私の場合の1は、単なるランダムな整数です。

1
Wingie