JavaFXアプリケーションを閉じるのに問題があります。ステージから閉じるボタンをクリックすると、アプリケーションが消えますが、タスクマネージャーでアプリケーションを探すと、アプリケーションは閉じずにまだそこにあります。以下のコードを使用して、メインスレッドとすべての子スレッドを強制的に閉じようとしましたが、問題は解決しません。
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
Platform.exit();
}
});
アプリケーションは子スレッドを生成しますか?もしそうなら、あなたはそれらを確実に終了させましたか(それらがデーモンスレッドではないと仮定して)?
アプリケーションがデーモン以外のスレッドを生成する場合、それらのスレッド(したがって、アプリケーション)は、プロセスを強制終了するような時間まで存続します。
唯一の方法は、System.exit(0)を呼び出すことでした。
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
});
[編集済み]
System.exitはアプリケーションを単に非表示にします。SOのマネージャータスクを開くと、アプリケーションはそこにあります。正しい方法は、スレッドを1つずつチェックして、アプリケーションを閉じる前にすべてを閉じることです。
public void start(Stage stage) {
Platform.setImplicitExit(true);
stage.setOnCloseRequest((ae) -> {
Platform.exit();
System.exit(0);
});
}
コントローラでThreadExecutorを使用しているときに、この問題が発生しました。 ThreadExecutorがシャットダウンされていない場合、アプリケーションは終了しません。ここを参照してください: how-to-shut-down-all-executors-when-quitting-an-application
コントローラーでアプリケーション出口を認識するのは問題になる可能性があるため、次のように(Eclipseのサンプルアプリケーションを使用して)Applicationクラスからコントローラーへの参照を取得できます。
public class Main extends Application {
private SampleController controller;
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml"));
BorderPane root = (BorderPane)loader.load(getClass().getResource("Sample.fxml").openStream());
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
controller = loader.<SampleController>getController();
}
catch(Exception e)
{
e.printStackTrace();
}
}
アプリケーションは、コントローラーのHousekeepingメソッドを呼び出すことができるstopメソッドをオーバーライドします(私はstartHousekeepingというメソッドを使用します)。
/**
* This method is called when the application should stop,
* and provides a convenient place to prepare for application exit and destroy resources.
*/
@Override
public void stop() throws Exception
{
super.stop();
if(controller != null)
{
controller.startHousekeeping();
}
Platform.exit();
System.exit(0);
}
com.Sun.javafx.application.tkExit()
を呼び出すことで、この問題を解決できました。詳細については、こちらの他の回答をご覧ください。 https://stackoverflow.com/a/22997736/1768232 (これらの2つの質問は実際には重複しています)。
注意事項:使用しているかどうかを確認してください
Platform.setImplicitExit(false);
同様の問題が発生し、タスクがオーバーフローしました。上記の行はステージを閉じるのではなく、非表示にします。
「x」を押すことを模倣するには、次のようにします。
stage.fireEvent(new WindowEvent(stage, WindowEvent.WINDOW_CLOSE_REQUEST))
いくつかのコードを使用して、閉じるボタンをクリックしてアプリケーションを閉じることができます。
stage.setOnCloseRequest(
event -> closeMyApp()
);
private void closeMyApp()
{
try
{
Stage stage = (Stage) closeButton.getScene().getWindow();
stage.close();
}
catch(Exception ee)
{
ex.printStackTrace();
}
}
// where closeButton is button having similar controller class initialization.
@FXML
private Button closeButton;