JavaFX: Stage close handler
Chcę zapisać plik przed zamknięciem aplikacji JavaFX.
Tak ustawiam Handlera w Main::start
:
primaryStage.setOnCloseRequest(event -> {
System.out.println("Stage is closing");
// Save file
});
I wywołanie kontrolera Stage::close
po naciśnięciu przycisku:
@FXML
public void exitApplication(ActionEvent event) {
((Stage)rootPane.getScene().getWindow()).close();
}
Jeśli zamknę okno klikając czerwony znak X na ramce okna (w normalny sposób), wtedy otrzymuję komunikat wyjściowy "Stage is closing
", który jest pożądanym zachowaniem.
Jednak podczas wywoływania Controller::exitApplication
aplikacja zamyka się bez wywoływania obsługi (nie ma wyjście).
Jak sprawić, by kontroler korzystał z funkcji obsługi, którą dodałem do primaryStage
?
3 answers
Jeśli spojrzeć na cykl życia klasy Application
:
Środowisko uruchomieniowe JavaFX wykonuje następujące czynności, w kolejności, gdy uruchomienie aplikacji:
- konstruuje instancję podanej klasy aplikacji
- wywołuje metodę
init()
- wywołuje metodę
start(javafx.stage.Stage)
- czeka na zakończenie aplikacji, co dzieje się, gdy wystąpi jedna z poniższych sytuacji:
- wywołanie aplikacji
Platform.exit()
- ostatnie okno zostało zamknięte, a atrybut
implicitExit
naPlatform
totrue
- wywołuje metodę
stop()
Oznacza to, że możesz wywołać Platform.exit()
na kontrolerze:
@FXML
public void exitApplication(ActionEvent event) {
Platform.exit();
}
Tak długo, jak nadpisujesz metodę stop()
na głównej klasie, aby zapisać plik.
@Override
public void stop(){
System.out.println("Stage is closing");
// Save file
}
Jak widzisz, używając stop()
nie musisz już nasłuchiwać żądań zamknięcia, aby zapisać plik (chociaż możesz to zrobić, jeśli chcesz zapobiec zamknięciu okna).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-23 18:57:43
Załóżmy, że chcesz zapytać użytkownika, czy chce zamknąć aplikację bez zapisywania pracy. Jeśli użytkownik wybierze opcję Nie, Nie można uniknąć zamknięcia aplikacji w metodzie stop. W tym przypadku powinieneś Dodać EventFilter do okna dla zdarzenia WINDOW_CLOSE_REQUEST.
W metodzie start dodaj ten kod, aby wykryć Zdarzenie:
(zauważ, że / align = "left" / exit (); nie uruchamia WindowEvent.WINDOW_CLOSE_REQUEST event, Zobacz poniżej know how to fire the event manually from a custom button)
// *** 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);
Następnie dodaj własną logikę. W moim przykładzie używam wyskakującego alertu, aby zapytać użytkownika, czy chce zamknąć aplikację bez zapisywania.
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();
}
}
}
Metoda event.consume()
zapobiega zamknięciu aplikacji . Oczywiście należy dodać co najmniej przycisk, który pozwala użytkownikowi zamknąć aplikację, aby uniknąć wymusić zamknięcie aplikacji przez użytkownika, że w niektórych przypadkach może uszkodzić dane.
Wreszcie, jeśli musisz odpalić Zdarzenie z niestandardowego przycisku zamykania, możesz użyć tego:
Window window = Main.getPrimaryStage() // Get the primary stage from your Application class
.getScene()
.getWindow();
window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-08 10:42:15
Ahh jest to znany błąd w JavaFX, gdzie scena nie zostanie zamknięta, jeśli w momencie zamykania jest obecne okno modalne. Podlinkuję Cię do raportu o błędzie, który właśnie dziś widziałem. I think {[2] } it is fixed in the latest release.
Proszę bardzo:
Https://bugs.openjdk.java.net/browse/JDK-8093147?jql=text%20~%20%22javafx%20re-entrant%22
Rozwiązany w 8.4 jest napisane. Myślę, że to właśnie opisujesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-08 14:02:12