JavaFX: метод и возврат, похоже, не работают должным образом - PullRequest
0 голосов
/ 28 мая 2020

'Доброе утро. Просто у меня небольшая проблема с java FX. Проблема в следующем: я хочу написать код и позволить появиться всплывающему окну, когда использование закроет приложение с помощью кнопки закрытия по умолчанию.

package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
    Stage window;
    Button button;
    boolean answer=false;
    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        window=primaryStage;
        window.setTitle("Homepage");
        window.setOnCloseRequest(e-> {
            e.consume();
            close();
        });
        StackPane layout = new StackPane();
        layout.getChildren().add(button);
        Scene scene = new Scene(layout, 300,300);
        window.setScene(scene);
        window.show();
    }
private void close(){ answer = ConfirmationBox.display("close app", "'sure about that?");
if(answer) {
    System.out.println(answer);
    window.close();
}
}
    public static void main(String[] args) {
        launch(args);
    }
}

каждый раз, когда я нажимаю кнопку закрытия приложения по умолчанию, появляется всплывающее окно сообщение вверх последует и спросит меня, хочу ли я закрыть приложение

 public static boolean display(String titolo,String messaggio){
        Stage window = new Stage();
        window.initModality(Modality.APPLICATION_MODAL);
        window.setTitle(titolo);
        Label label=new Label();
        label.setText(messaggio);


        Button yButton = new Button("yes");
        Button nButton = new Button("no");

        yButton.setOnAction(e-> {
            flag=true;
            window.close();
        });

        nButton.setOnAction(e-> {
            flag=false;
            window.close();
        });

        VBox layout = new VBox(20);
        layout.minHeight(250);
        layout.getChildren().addAll(label,yButton,nButton);
        layout.setAlignment(Pos.CENTER);
        Scene scene = new Scene(layout,300,300);
        window.setScene(scene);
        window.show();

        return flag;

Проблема в том, что когда я впервые запускаю метод, логическая переменная «answer» не могла правильно сохранить результат, поэтому close () не может войти внутрь случая if. как предотвратить это? я пропустил некоторые функции javaFX? Я новичок в javaFX и самом java.

Ответы [ 3 ]

4 голосов
/ 28 мая 2020

Попробуйте что-нибудь вроде этого.

primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        @Override
        public void handle(WindowEvent event) {
            Alert alert = new Alert(AlertType.CONFIRMATION);
            alert.setTitle("Exit Application");
            alert.setContentText("Do you want to exit?");

            Optional<ButtonType> result = alert.showAndWait();

            if (result.isPresent() && result.get() != ButtonType.OK) {
                event.consume();
            }
        }
    });
}
2 голосов
/ 28 мая 2020

Метод Window.show() показывает окно и сразу возвращает . Поэтому ваш код

public static boolean display(String titolo,String messaggio){

    // ...

    window.show();

    return flag;
}

отобразит окно и немедленно вернет текущее значение flag (которое изначально равно false).

Если пользователь нажимает yButton, флаг , затем установлен на true, и в следующий раз, когда они попытаются закрыть главное окно, метод немедленно вернет true, и главное окно закроется.

Вместо этого вы можете используйте метод window.showAndWait(), который «Показывает этот этап и ждет, пока он не будет скрыт (закрыт), прежде чем вернуться к вызывающему.»:

public static boolean display(String titolo,String messaggio){

    // ...

    // window.show();
    window.showAndWait();

    return flag;
}

Как указывали другие ответы , есть также Dialog API , включая удобный Alert класс . Основная функциональность, которую Dialog предоставляет, а не Stage - это возможность возвращать значение из метода showAndWait(). В вашем случае вы хотите вернуть boolean, поэтому версия вашего метода на основе Dialog будет выглядеть так:

public static boolean display(String titolo,String messaggio){

    Dialog<Boolean> dialog = new Dialog<>();
    dialog.setTitle(titolo);
    dialog.getDialogPane().setContentText(messaggio);
    dialog.getDialogPane().getButtonTypes().addAll(
        ButtonType.YES, ButtonType.NO);

    // Result of dialog is true if button is YES button, 
    // false otherwise
    dialog.setResultConverter(button -> button == ButtonType.YES);

    // return result of dialog, or false if there is no result
    // (i.e. if user closes dialog without pressing a button)
    return dialog.showAndWait().orElse(false);
}
0 голосов
/ 28 мая 2020

Я сам новичок в Java, поэтому прекрасно понимаю, где вы сейчас находитесь.

Я предполагаю, что ваш основной метод продолжает работать после появления диалогового окна подтверждения, поэтому ответ все еще ложь в первый раз. Возможно, вам придется оставить свой основной метод в ожидании, пока пользователь все еще думает, закрывать ли программу или нет.

Если ваш класс ConfirmationBox расширяет класс DialogPane, вы можете использовать метод window.showAndWait() вместо window.show() внутри display(). Я думаю, что это должно сработать.

Надеюсь, это поможет!

Edit: На самом деле, я только что понял, что это решение не зависит от того, расширяет ли ConfirmationBox DialogPane, поскольку window является объектом Stage и уже включает метод showAndWait().

...