2017-02-23 4 views
14

にその舞台をもたらし、私は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(); 
    } 
} 

主要ステージ上のボタンが推移した場合、それは目の前に来ます第2段階ステージ上でinitOwner()と呼ぶと、この動作がなくなることがわかりました。

私の問題は次のとおりです。共通の所有者(プライマリステージ)を持つ複数の「ポップアップ」があります。プライマリステージ上のコントロールをホバリングしても、initOwner()回避策の後に予期しない動作が発生することはありません。しかし、別のポップアップがフォーカスされているときにポップアップのコントロールにマウスを合わせると、ポップアップされたポップアップがフォーカスを奪います。

プライマリステージだけでなくポップアップでもこのバグを回避する方法はありますか?

UPDATE:私の回避策には、望ましくない副作用があることが判明しました。次のステージ状態のJavadocs:

ステージは常に親ウィンドウの上に表示されます。

さらに、ポップアップを「常に上に」ないし最小限に抑えるための回避策はありますか?

答えて

4

StackPanesをオーバーレイして回避する方法があります。 をStackPaneで作成し、ステージのフォーカスが失われたときに別のStackPaneを追加することができます。オーバーレイされたペインは、ウィンドウがフォーカスされていない間にマウスオーバーで起きることを防ぎます。Tooltipあなたはまたあなたのステージを最小限に抑えることができ、いつでもトップになることはありません。

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); 
       } 
      } 
     }); 
    } 
} 
+0

が、これはツールチップの数が多いとうまく動作します本当に素晴らしいソリューションですありがとう...私にとっては魅力のように働いています! – Selim

1

ノードのウィンドウがフォーカスを失うと、ツールチップの設定を解除することができます。このような次のように:もちろん

public class Blubb extends Application { 
    public static void main(String[] args) { 
     launch(args); 
    } 

    public static void installTooltip(Node n, Tooltip tp) 
    { 
     Window w = n.getScene().getWindow(); 
     w.focusedProperty().addListener((val, before, after) -> { 
      if (after) 
       Tooltip.install(n, tp); 
      else 
       Tooltip.uninstall(n, tp); 
     }); 

     if (w.isFocused()) 
      Tooltip.install(n, tp); 
     else 
      Tooltip.uninstall(n, tp); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     Tooltip tp = new Tooltip("Blubb"); 
     Button btn = new Button("Click"); 

     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(); 
     primaryStage.show(); 

     installTooltip(btn, tp); 
    } 
} 

、あなたはノードがコンポーネントに追加された後installTooltipを呼び出す必要があります。

3

あなたはこれを試すことができます。

public static final disableMouseEventOnUnfocus(final Stage stage) 
{ 
    if (stage == null 
     || stage.getScene() == null 
     || stage.getScene().getRoot() == null) 
     return; 
    else 
    { 
     stage.getScene().getRoot().mouseTransparentProperty().bind(stage.focusedProperty().not()); 
    } 
} 

でも、私はそれを試していなかったが、それが動作するかどうか、これは良い選択肢でなければなりません。レイアウトを再構成する必要はなく、fx:idをツールチップに指定することなく、すべてのレイアウトをFXMLにすることができます。

+0

これは機能し、とても簡潔です! – Selim

2

私の場合、ツールチップをサブクラス化してそこに修正を適用する方が簡単だと分かったので、この代替ソリューションを考え出しました。私はshow()メソッドをオーバーロードして、所有ウィンドウがフォーカスされているかどうかを表示します。

public class FixedTooltip extends Tooltip { 

    public FixedTooltip(String string) { 
     super(string); 
    } 

    @Override 
    protected void show() {   
     Window owner = getOwnerWindow();   
     if (owner.isFocused()) 
      super.show(); 
    }  

} 
+0

これは、ホバー、入力、終了などのマウス関連イベントを保持します。ニースの解決策! – Selim

関連する問題