Non c'è alcuna funzionalità built-in per questo. Nella maggior parte dei casi d'uso, si apre un nuovo Stage
come conseguenza dell'azione dell'utente, quindi è possibile chiamare getScene().getWindow()
sul nodo su cui si è verificata l'azione per ottenere la finestra "corrente".
In altri casi di utilizzo, è necessario scrivere codice per tenere traccia delle finestre correnti. Naturalmente, più finestre potrebbero essere aperte, quindi è necessario rintracciarle in una sorta di raccolta. Ti consigliamo di creare una classe factory per gestire le fasi e registrare i gestori di eventi per le fasi di apertura e chiusura, in modo da poter aggiornare una proprietà e/o un elenco. Probabilmente vorrai che sia un singleton. Ecco un'implementazione esemplificativa: qui getOpenStages()
fornisce un elenco osservabile di fasi aperte - l'ultima è l'ultima aperta- e currentStageProperty()
fornisce lo stage focalizzato (se presente). La tua esatta implementazione potrebbe essere diversa, a seconda delle tue esigenze.
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 ;
}
}
Nota questo consente solo di monitorare le fasi ottenuti da StageFactory.INSTANCE.createStage()
o creati altrove e passati al metodo StageFactory.INSTANCE.registerStage(...)
, in modo che il codice deve collaborare con tale obbligo. D'altra parte, ti dà la possibilità di centralizzare il codice che inizializza i tuoi stadi, che potrebbe essere altrimenti vantaggioso.
Ecco un semplice esempio che utilizza questo:
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);
}
}
fonte
2015-10-03 16:27:01
AFAIK non c'è modo di farlo. Qual è il contesto per questo? Forse c'è un altro modo per fare quello che vuoi. Se questo è in risposta a un'azione dell'utente, puoi sempre ottenere la finestra contenente la finestra contenente un nodo con 'node.getScene(). GetWindow()'. –
La notifica mostra all'interno di un ciclo "infinito" all'interno di un thread. In questo thread, non ho il riferimento a nessuna finestra, perché il thread viene avviato dalla prima finestra dell'applicazione (finestra di accesso) che si chiude dopo che l'utente accede al sistema, ma il thread continua a essere in esecuzione. –