Как получить текущий открытый этап в 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();
}