Search code examples
javafxstage

JFX: Lock a stage ontop of another stage / detect stage order


Let's say I have three Java FX stages: A, B and C. Each with their own open window and am aiming for the following behavior:

If A takes focus, B should appear ontop and C ontop of B -> A-B-C

If B is taking focus, Be should appear in front of C and A in the back -> A-C-B

If C is taking focus, naturally -> A-B-C

Am aware of the toFront() function and have tried to manually enforce the order correspondingly by simply calling toFront() to every stage in the right order whenever one of the stages regains focus, however that results in undesired flickering because there is apparently no way to determine which windows are already in the right place.

Unfortunately I cannot use the modal-window system because all windows need to remain operational in parallel.

Is there any way to achieve this?

Huge thanks in advance!


Solution

  • Just had the same problem. The only "hack" i could find is to store the order in which the stages got focus and then travel in reverse order through all stages and call .toFront().

    Whenever a stage gets the Focus i put in on Top of the List of open stages. I then block the EventHandler globaly because every time a stage receives the .toFont() call it also gets the Focus.

    Works well on Mac. Does not work and shows a strange behavior under Windows

    this.model.stage.focusedProperty().addListener((ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) -> {
            if (!mainModel.blockFocusRequest){
            if (t1){
                try{
                    mainModel.openWindows.remove(this.model.stage);
                    mainModel.openWindows.add(0,this.model.stage);
                mainModel.blockFocusRequest = true;
                for (int i=mainModel.openWindows.size()-1;i>=0;i--){
                    mainModel.openWindows.get(i).toFront();
                }                              
                } finally{
                    mainModel.blockFocusRequest = false;
                }
            }
            }
        });