Как получить текущий открытый этап в JavaFX?

есть ли способ получить текущий открытый этап в JavaFX, если есть один открытый?

что-то вроде этого:

Stage newStage = new Stage();
newStage.initOwner(JavaFx.getCurrentOpenedStage()); //Like this

3 ответов


для этого нет встроенной функциональности. В большинстве случаев вы открываете новое Stage в результате действия пользователя, поэтому вы можете вызвать getScene().getWindow() на узле, на котором произошло действие, чтобы получить "текущее окно".

в других случаях использования вам придется написать код для отслеживания текущих окон самостоятельно. Конечно, может быть открыто несколько окон, поэтому вам нужно отслеживать их в какой-то коллекции. Я бы рекомендовал создать класс factory для управления этапами и регистрации события обработчики для открытия и закрытия этапов, так что вы можете обновить свойство и / или список. Вы, наверное, хотите, чтобы это был синглтон. Вот пример реализации: here getOpenStages() дает наблюдаемый список открытых этапов-последний из них является самым последним открытым - и currentStageProperty() дает сфокусированный этап (если таковые имеются). Ваша точная реализация может отличаться, в зависимости от ваших конкретных потребностей.

public enum StageFactory {
    INSTANCE ;

    private final ObservableList<Stage> openStages = FXCollections.observableArrayList();

    public ObservableList<Stage> getOpenStages() {
        return openStages ;
    }

    private final ObjectProperty<Stage> currentStage = new SimpleObjectProperty<>(null);
    public final ObjectProperty<Stage> currentStageProperty() {
        return this.currentStage;
    }
    public final javafx.stage.Stage getCurrentStage() {
        return this.currentStageProperty().get();
    }
    public final void setCurrentStage(final javafx.stage.Stage currentStage) {
        this.currentStageProperty().set(currentStage);
    }

    public void registerStage(Stage stage) {
        stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> 
                openStages.add(stage));
        stage.addEventHandler(WindowEvent.WINDOW_HIDDEN, e -> 
                openStages.remove(stage));
        stage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
            if (isNowFocused) {
                currentStage.set(stage);
            } else {
                currentStage.set(null);
            }
        });
    }

    public Stage createStage() {
        Stage stage = new Stage();
        registerStage(stage);
        return stage ;
    }

}

обратите внимание, что это позволяет отслеживать только этапы, полученные из StageFactory.INSTANCE.createStage() или создан в другом месте и перешел к StageFactory.INSTANCE.registerStage(...) метод, поэтому ваш код должен сотрудничать с этим требованием. С другой стороны, это дает вам возможность централизовать код, который инициализирует ваши этапы, что в противном случае может быть полезно.

вот простой пример использования этого:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class SceneTrackingExample extends Application {

    int count = 0 ;

    @Override
    public void start(Stage primaryStage) {
        StageFactory factory = StageFactory.INSTANCE ;
        factory.registerStage(primaryStage);

        configureStage(primaryStage);
        primaryStage.show();
    }

    private void configureStage(Stage stage) {
        StageFactory stageFactory = StageFactory.INSTANCE;
        Stage owner = stageFactory.getCurrentStage() ;
        Label ownerLabel = new Label();
        if (owner == null) {
            ownerLabel.setText("No owner");
        } else {
            ownerLabel.setText("Owner: "+owner.getTitle());
            stage.initOwner(owner);
        }
        stage.setTitle("Stage "+(++count));
        Button newStage = new Button("New Stage");
        newStage.setOnAction(e -> {
            Stage s = stageFactory.createStage();
            Stage current = stageFactory.getCurrentStage() ;
            if (current != null) {
                s.setX(current.getX() + 20);
                s.setY(current.getY() + 20);
            }
            configureStage(s);
            s.show();
        });

        VBox root = new VBox(10, ownerLabel, newStage);
        root.setAlignment(Pos.CENTER);
        stage.setScene(new Scene(root, 360, 150));
    }

    public enum StageFactory {
        INSTANCE ;

        private final ObservableList<Stage> openStages = FXCollections.observableArrayList();

        public ObservableList<Stage> getOpenStages() {
            return openStages ;
        }

        private final ObjectProperty<Stage> currentStage = new SimpleObjectProperty<>(null);
        public final ObjectProperty<Stage> currentStageProperty() {
            return this.currentStage;
        }
        public final javafx.stage.Stage getCurrentStage() {
            return this.currentStageProperty().get();
        }
        public final void setCurrentStage(final javafx.stage.Stage currentStage) {
            this.currentStageProperty().set(currentStage);
        }

        public void registerStage(Stage stage) {
            stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> 
                    openStages.add(stage));
            stage.addEventHandler(WindowEvent.WINDOW_HIDDEN, e -> 
                    openStages.remove(stage));
            stage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
                if (isNowFocused) {
                    currentStage.set(stage);
                } else {
                    currentStage.set(null);
                }
            });
        }

        public Stage createStage() {
            Stage stage = new Stage();
            registerStage(stage);
            return stage ;
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

Java 9 делает это возможным путем добавления javafx.stage.Window.getWindows() метод. Поэтому вы можете просто получить список окон и посмотреть, какие из них показывают

List<Window> open = Stage.getWindows().filtered(window -> window.isShowing());

вы можете создать метку в java fxml.

затем в вашем классе контроллера обратитесь к вашей метке следующим образом:

@FXML private Label label;

тогда в любой функции класса контроллера вы можете получить доступ к текущему этапу с помощью этого блока кода:

private void any_function(){
        Stage stage;
        stage=(Stage) label.getScene().getWindow();
}