I am trying to work around this bug in the jdk: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8088624
public class Blubb extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Button btn = new Button("Click");
btn.setTooltip(new Tooltip("Blubb"));
Scene scene = new Scene(new BorderPane(btn), 320, 240);
primaryStage.setScene(scene);
primaryStage.show();
Stage secondStage = new Stage();
secondStage.setScene(new Scene(new BorderPane(new Button("Click")), 320, 240));
//secondStage.initOwner(primaryStage);
secondStage.show();
}
}
If the button on the primary stage is hovered, it will come in front of the second stage. I found that calling initOwner()
on a Stage will eliminate this behavior.
Now my problem is following: I have multiple "popups" that have a common owner (the primary stage). Hovering over controls on the primary stage doesn't cause any unexpected behavior after the initOwner()
workaround. If you however hover over controls in a popup while another popup was in focus, the hovered popup will steal focus.
Is there a way I can work around this bug for not only the primary stage but also the popups?
UPDATE: turns out my workaround has undesired side-effects. Javadocs for Stage state following:
A stage will always be on top of its parent window.
So additionally, what would be a workaround that makes the popup not "always on top" and minimizable?
There is a way to get around it by overlaying StackPanes. Create your Scene
with a StackPane
so that you can add another StackPane
when the stage has lost its focus. The overlayed pane will prevent Tooltip
s or anything else happening on mouse-over while the pane is not in focus. You may also minimize any of your stages and they won't be always-on-top.
public class Blubb extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Button button_1 = new Button("Button #1");
button_1.setTooltip(new Tooltip("Blubb #1"));
StackPane primary = new StackPane(new BorderPane(button_1));
primaryStage.setScene(new Scene(primary, 320, 240));
addStageFocusListener(primaryStage, primary);
primaryStage.show();
Button button_2 = new Button("Button #2");
button_2.setTooltip(new Tooltip("Blubb #2"));
StackPane second = new StackPane(new BorderPane(button_2));
Stage secondStage = new Stage();
addStageFocusListener(secondStage, second);
secondStage.setScene(new Scene(second, 320, 240));
secondStage.show();
}
public void addStageFocusListener(Stage stage, StackPane stackPane) {
stage.focusedProperty().addListener(new ChangeListener<Boolean>(){
public final StackPane preventTooltip = new StackPane();
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(stage.isFocused()) {
if(stackPane.getChildren().contains(preventTooltip)) {
stackPane.getChildren().remove(preventTooltip);
}
} else {
stackPane.getChildren().add(preventTooltip);
}
}
});
}
}