2017-07-07 4 views
0

Pour mon application, j'ai besoin de savoir à chaque fois que la fenêtre de l'application est mise au point ou non. Pour cela, je peux utiliser primaryStage.focusedProperty().addListener(..), qui m'avertira des changements de mise au point de la scène.javafx - Alerte et mise au point

Mais je me suis rendu compte que l'ouverture d'un Alert avec ce primaryStage en tant que propriétaire et modalité mis à WINDOW_MODAL rend la mise au point primaryStage lâche (même si la fenêtre est en réalité concentrée, ou au moins sous Windows).

Maintenant le problème que j'ai est que je veux savoir quand le Window est concentré et pas seulement le primaryStage; ou au moins savoir si le Alert est focalisé, mais je n'ai pas pu trouver comment. J'ai essayé d'utiliser des propriétés similaires sur l'alerte (comme onShowing et onHiding) sans succès.

Voici un morceau de code pour illustrer mon problème:

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

Fondamentalement, il imprimera ceci:

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' 

Ce qui est étrange à cause de toutes les autres impressions qu'il doit produire. également idéalement je besoin d'un:

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 

ou quelque chose de similaire. Est-ce que quelqu'un a une idée pour y parvenir, ou est-ce primaryStage perdre l'accent sur un WINDOW_MODALAlert un problème que je devrais signaler?

Répondre

0

Donc finalement, je pourrais trouver une solution de contournement. Il est possible pour chaque buttonType utilisé dans une alerte de déterminer si elle est focalisée ou non. Cette propriété change aussi quand alt + tabbing, ainsi nous pouvons surveiller chaque buttonType utilisé et voir si seulement un est focalisé ou pas.

Voici ma solution, un peu hacky mais la réalisation de ce que je voulais:

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

Je pense que je peux aussi étendre cette méthode de dialogue en ajoutant un chèque de alert.getDialogPane().isFocused() dans la méthode isAlertFocused(Alert alert), mais cela est hors de la portée de ma question.