2015-10-03 8 views
6

C'è un modo per ottenere lo stage corrente aperto in JavaFX, se ce n'è uno aperto?Come ottenere l'attuale fase aperta in JavaFX?

Qualcosa di simile a questo:

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

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()'. –

+0

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. –

risposta

9

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); 
    } 
} 
3

Java 9 rende questo possibile con l'aggiunta del metodo javafx.stage.Window.getWindows(). Pertanto è possibile ottenere solo l'elenco di Windows e vedere che stanno visualizzando

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