2016-05-03 10 views
4

OS Xのデフォルトの「ウィンドウ」メニューに似た、JavaFX用のウィンドウメニューを作成しています。このメニューには、アプリケーションのウィンドウのリストがあり、 1。注目のステージが変更されたときに通知を受け取ります

私は自動的に削除されたり、新しく作成されたウィンドウに反応するように私にObservableListを与える

StageHelper.getStages() 

からのすべてのウィンドウのリストを取得しています。左にあるのは、現在フォーカスされているウィンドウでメニュー項目をマークすることです。フォーカスされたステージが変わるとすぐに通知を受ける必要があるため、フォーカスされたステージを積極的にチェックしたくありません。

私の現在のアイデアは、作成されたすべてのステージにフォーカスリスナーを追加することですが、他に何かがあるかどうか疑問に思っていました。現在フォーカスされているステージに観測可能なプロパティを保持するヘルパークラスがありますか?

+0

脇: 'StageHelper'がプライベートAPIであり、非常に強く(それは例えば、Javaの9でアクセスすることはできません)、それを使用しないことをお勧めします。 –

+0

はい、わかっています。私はJava 8の唯一のソリューションを探しています。 –

答えて

4

まず、非公開APIを使用しないことを強くお勧めします。 StageFactoryクラスを作成し、プライマリステージで初期化し、新しいステージをリクエストする方がよいでしょう。その後、あなたのためのすべてのステージを追跡することができます(また、簡単に焦点を当てたステージを追跡することもできます)。

このようにしたい場合は、focusedPropertyへのエクストラクタマッピングを使用してObservableList<Stage>を作成し、その内容を既存のステージリストにバインドします。次に、フォーカスされたプロパティが変更された場合、新しいリストが更新されます。

SSCCE:

import com.sun.javafx.stage.StageHelper; 

import javafx.application.Application; 
import javafx.beans.Observable; 
import javafx.beans.binding.Bindings; 
import javafx.collections.FXCollections; 
import javafx.collections.ListChangeListener.Change; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class TrackFocusedStage extends Application { 

    int stageCount = 1 ; 
    @Override 
    public void start(Stage primaryStage) { 
     ObservableList<Stage> stages = FXCollections.observableArrayList(stage -> new Observable[] {stage.focusedProperty()}); 
     Bindings.bindContent(stages, StageHelper.getStages()); 
     Label label = new Label(); 
     stages.addListener((Change <? extends Stage> c) -> 
      label.setText(
        stages.stream() 
        .filter(Stage::isFocused) 
        .findAny() 
        .map(Stage::getTitle) 
        .orElse(""))); 

     Button newStageButton = new Button("New Window"); 
     newStageButton.setOnAction(e -> newStage()); 
     Scene scene = new Scene(new BorderPane(new StackPane(newStageButton), label, null, null, null), 300, 180); 
     primaryStage.setScene(scene); 
     primaryStage.setTitle("Primary"); 
     primaryStage.show(); 
    } 

    private void newStage() { 
     Stage stage = new Stage(); 
     stage.setTitle("Window "+(++stageCount)); 
     Button close = new Button("Close"); 
     close.setOnAction(e -> stage.hide()); 
     stage.setScene(new Scene(new StackPane(close), 300, 80)); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
関連する問題