2015-10-03 56 views
6

有沒有辦法在JavaFX中獲得當前打開的舞臺,如果有一個打開?如何在JavaFX中獲取當前打開的階段?

事情是這樣的:

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

AFAIK有沒有辦法做到這一點。這是什麼情況?也許還有另一種方法去做你想做的事。如果這是對用戶操作的響應,則可以始終通過'node.getScene()。getWindow()'獲取包含窗口的窗口。 –

+0

通知顯示在線程內的「無限」循環內。在這個線程中,我沒有對任何窗口的引用,因爲線程是從第一個應用程序窗口(登錄窗口)開始的,在用戶登錄到系統後關閉該線程,但線程仍在運行。 –

回答

9

有這個沒有內置的功能。在大多數使用情況下,由於用戶操作,您會打開一個新的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, 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使這成爲可能通過添加javafx.stage.Window.getWindows()方法。因此,你可以得到Windows列表,看看哪些顯示

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