有没有办法在
JavaFX中获得当前打开的Stage,如果有一个打开的话?
像这样的东西:
Stage newStage = new Stage(); newStage.initOwner(JavaFx.getCurrentOpenedStage()); //Like this
解决方法
这没有内置功能.在大多数用例中,由于用户操作而打开一个新的Stage,因此可以在发生操作的节点上调用getScene().getWindow()以获取“当前”窗口.
在其他用例中,您必须编写代码来自己跟踪当前窗口.当然,多个窗口可能是打开的,因此您需要在某种集合中跟踪它们.我建议创建一个工厂类来管理阶段并为阶段的打开和关闭注册事件处理程序,这样您就可以更新属性和/或列表.你可能希望这是一个单身人士.这是一个示例实现:这里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,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); } }