JavaFX: Stade proche de gestionnaire
je veux enregistrer un fichier avant de fermer mon application JavaFX.
Voici comment j'installe le handler dans Main::start
:
primaryStage.setOnCloseRequest(event -> {
System.out.println("Stage is closing");
// Save file
});
et le contrôleur appelant Stage::close
quand un bouton est appuyé:
@FXML
public void exitApplication(ActionEvent event) {
((Stage)rootPane.getScene().getWindow()).close();
}
si je ferme la fenêtre en cliquant sur le X rouge sur la bordure de la fenêtre (de la manière habituelle), alors j'obtiens le message de sortie"Stage is closing
", qui est le comportement souhaité.
Toutefois, lors de l'appel de Controller::exitApplication
l'application se ferme sans invoquer l' gestionnaire (il n'y a pas de sortie).
Comment faire pour que le controller utilise le handler que j'ai ajouté à <!--6?
3 réponses
Si vous avez un coup d'oeil à l' cycle de vieApplication
catégorie:
L'exécution JavaFX fait ce qui suit, dans l'ordre, chaque fois qu'un l'application est lancée:
- Construit une instance de la classe d'Application
- Appelle
init()
méthode- Appelle
start(javafx.stage.Stage)
méthode- attend que l'application se termine, ce qui se produit lorsque l'une des situations suivantes se produit:
- l'application appelle
Platform.exit()
- la dernière fenêtre a été fermée et les
implicitExit
attributPlatform
true
- Appelle
stop()
méthode
Cela signifie que vous pouvez appeler Platform.exit()
sur votre contrôleur:
@FXML
public void exitApplication(ActionEvent event) {
Platform.exit();
}
tant que vous remplacer le stop()
méthode de la classe principale pour enregistrer le fichier.
@Override
public void stop(){
System.out.println("Stage is closing");
// Save file
}
comme vous pouvez le voir, en utilisant stop()
vous ne le faites pas être à l'écoute de fermer les demandes pour enregistrer le fichier (si vous pouvez le faire si vous voulez empêcher la fermeture de fenêtre).
Supposons que vous voulez demander à l'utilisateur si il veut quitter l'application sans enregistrer le travail. Si l'utilisateur choisit non, vous ne pouvez pas éviter l'application pour fermer dans la méthode d'arrêt. Dans ce cas, vous devez ajouter un EventFilter à votre fenêtre pour un événement WINDOW_CLOSE_REQUEST.
Dans votre méthode de démarrage ajouter ce code pour détecter l'événement:
(Notez que plate-forme d'appel.exit(); ne pas le feu à la WindowEvent.WINDOW_CLOSE_REQUEST événement, voir ci-dessous pour savoir comment déclencher l'événement manuellement à partir d'un bouton personnalisé)
// *** Only for Java >= 8 ****
// ==== This code detects when an user want to close the application either with
// ==== the default OS close button or with a custom close button ====
primaryStage.getScene().getWindow().addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, this::closeWindowEvent);
alors ajoutez votre logique personnalisée. Dans mon exemple, j'utilise une Alerte popup pour demander à l'utilisateur si il/elle veut fermer l'application sans enregistrer.
private void closeWindowEvent(WindowEvent event) {
System.out.println("Window close request ...");
if(storageModel.dataSetChanged()) { // if the dataset has changed, alert the user with a popup
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.getButtonTypes().remove(ButtonType.OK);
alert.getButtonTypes().add(ButtonType.CANCEL);
alert.getButtonTypes().add(ButtonType.YES);
alert.setTitle("Quit application");
alert.setContentText(String.format("Close without saving?"));
alert.initOwner(primaryStage.getOwner());
Optional<ButtonType> res = alert.showAndWait();
if(res.isPresent()) {
if(res.get().equals(ButtonType.CANCEL))
event.consume();
}
}
}
event.consume()
méthode empêche la fermeture de l'application. Évidemment, vous devez ajouter au moins un bouton qui permet à l'utilisateur de fermer l'application pour éviter de forcer la fermeture de l'application par l'utilisateur, qui dans certains cas peut corrompre des données.
enfin, si vous devez feu de l'événement personnalisé à partir d'un bouton de fermeture, vous pouvez utiliser ceci :
Window window = Main.getPrimaryStage() // Get the primary stage from your Application class
.getScene()
.getWindow();
window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
Ahh il s'agit d'un bug connu dans JavaFX où L'étape ne se fermera pas si un dialogue modal est présent au moment de la fermeture. Je vais vous relier au rapport de bogue que je viens de voir aujourd'hui. J' penser c'est corrigé dans la dernière version.
Ici, vous allez:
https://bugs.openjdk.java.net/browse/JDK-8093147?jql=text%20~%20%22javafx%20re-entrant%22
résolu à la Section 8.4. Je pense que ce que vous décrivez.