2017-07-07 47 views
0

對於我的應用程序,我需要知道應用程序的窗口是否聚焦。爲此,我可以使用primaryStage.focusedProperty().addListener(..),它會警告我舞臺焦點的變化。javafx - 警報和舞臺焦點

但我已經意識到這個primaryStage作爲所有者和使用模式設置爲WINDOW_MODAL開設Alert使得primaryStage寬鬆焦點(即使窗口在現實中集中,或至少在Windows)。

現在我有的問題是,我想知道什麼時候Window是重點,而不僅僅是primaryStage;或至少知道Alert是否集中,但我無法找到如何。

我嘗試在警報上使用類似屬性(如onShowingonHiding),但未成功。

下面是一段代碼來說明我的問題:

package sample; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Alert; 
import javafx.stage.Modality; 
import javafx.stage.Stage; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); 
     primaryStage.setTitle("Hello World"); 
     primaryStage.setScene(new Scene(root, 300, 275)); 

     primaryStage.focusedProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("primaryStage focused : "+newValue); 
     }); 
     primaryStage.show(); 

     //create a basic alert 
     Alert alert = new Alert(Alert.AlertType.INFORMATION,"This is a test"); 
     alert.initModality(Modality.WINDOW_MODAL); //will block input to its owner window 
     alert.initOwner(primaryStage); 
     alert.onShowingProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("alert onShowing : "+newValue); 
     }); 
     alert.onShownProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("alert onShown : "+newValue); 
     }); 
     alert.onHidingProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("alert onHiding : "+newValue); 
     }); 
     alert.onHiddenProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("alert onHidden : "+newValue); 
     }); 
     alert.showAndWait(); 
    } 


    public static void main(String[] args) { 
     launch(args); 
    } 
} 

基本上,它會打印:

primaryStage focused : true //stage is created and displayed 
primaryStage focused : false //alert is displayed, stage loses focus. alt+tab changes nothing 
primaryStage focused : true //alert closed by pressing 'ok' 

,因爲它應該產生的所有其他打印這是奇怪的。 理想情況下,我會需要一個:

primaryStage focused : true //stage is created and displayed 
primaryStage focused : false //alert is displayed, stage loses focus 
alert focused : true //alert gains focus 
alert focused : false //alt+tab to an other window 
alert focused : true //alt+tab back to this window 
alert focused : false //alert closed by pressing 'ok' 
primaryStage focused : true //stage regains focus 

或類似的東西。有沒有人有想法實現這個目標,或者這是primaryStage失去焦點到WINDOW_MODALAlert我應該報告的問題?

回答

0

因此,最後我可以找到一個解決方法。警報中使用的每個buttonType都有可能確定它是否被聚焦。此屬性也會在alt + tab鍵時發生變化,因此我們可以監視每個buttonType的使用情況,看看是否只有一個焦點。

這裏我的解決辦法,有點哈克但實現我想要的東西:

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Alert; 
import javafx.scene.control.ButtonType; 
import javafx.stage.Modality; 
import javafx.stage.Stage; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); 
     primaryStage.setTitle("Hello World"); 
     primaryStage.setScene(new Scene(root, 300, 275)); 

     primaryStage.focusedProperty().addListener((observable, oldValue, newValue) -> { 
      System.out.println("PrimaryStage focused : "+newValue); 
     }); 
     primaryStage.show(); 

     //create a basic alert 
     Alert alert = new Alert(Alert.AlertType.CONFIRMATION,"This is a test"); 
     alert.initModality(Modality.WINDOW_MODAL); //will block input to its owner window 
     alert.initOwner(primaryStage); 

     alert.getButtonTypes().forEach(buttonType -> { 
      //add a focus listnener for each buttonType of this alert 
      alert.getDialogPane().lookupButton(buttonType).focusedProperty().addListener((observable, oldValue, newValue) -> { 
       System.out.println(buttonType.getText()+" focused : "+newValue); 
       System.out.println("Alert focused : "+isAlertFocused(alert)); 

      }); 
     }); 
     alert.showAndWait(); 
    } 

    /** Looks all {@link ButtonType} used in the given {@link Alert} and checks if any of them is 
    * focused, hence if the {@link Alert} is being focused 
    * 
    * @param alert the {@link Alert} we want to check the focused status from 
    * @return true if the alert is focused, false otherwise 
    */ 
    private boolean isAlertFocused(Alert alert){ 
     if(alert == null){ 
      return false; 
     } 

     final boolean[] focused = {false}; 
     alert.getButtonTypes().forEach(buttonType -> { 
      focused[0] = focused[0] || alert.getDialogPane().lookupButton(buttonType).isFocused(); 
     }); 
     return focused[0]; 
    } 


    public static void main(String[] args) { 
     launch(args); 
    } 
} 

我想我也可以這種方法通過增加isAlertFocused(Alert alert)方法內部的alert.getDialogPane().isFocused()檢查擴展到對話框,但是這是出我的問題的範圍。