2017-07-07 7 views
0

Für meine Anwendung muss ich wissen, wann das Fenster der App fokussiert wird oder nicht. Dafür kann ich primaryStage.focusedProperty().addListener(..) verwenden, was mich vor Änderungen im Fokus der Bühne warnt.javafx - Alarm- und Bühnenfokus

Aber ich habe erkannt, dass eine Alert mit diesem primaryStage als Eigentümer zu öffnen und mit Modalität auf WINDOW_MODAL macht die primaryStage lose Fokus (auch wenn das Fenster in Wirklichkeit fokussiert ist, oder zumindest in Windows).

Jetzt das Problem, das ich habe, ist, dass ich wissen will, wenn die Window konzentriert ist und nicht nur die ; oder zumindest wissen, ob der Alert fokussiert ist, aber ich konnte nicht finden, wie.

Ich habe versucht, ähnliche Eigenschaften in der Warnung (wie onShowing und onHiding) ohne Erfolg zu verwenden.

Hier ist ein Stück Code, um mein Problem zu veranschaulichen:

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

Grundsätzlich wird es dieses Motiv:

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' 

die wegen aller anderen Drucke seltsam ist, dass sie produzieren soll. Auch ideal wäre ich brauche:

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 

oder etwas ähnliches. Hat jemand eine Idee, dies zu erreichen, oder ist das primaryStage Fokus auf WINDOW_MODALAlert verlieren ein Problem, das ich melden sollte?

Antwort

0

So endlich könnte ich einen Workaround finden. Es ist möglich, für jede buttonType, die in einer Warnung verwendet wird, festzustellen, ob sie fokussiert ist oder nicht. Diese Eigenschaft ändert sich auch, wenn alt + tabbing, so können wir alle verwendeten buttonType überwachen und sehen, ob nur einer fokussiert ist oder nicht.

Hier ist meine Lösung, ein bisschen hacky aber zu erreichen, was ich wollte:

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

Ich glaube, ich kann diese Methode auch auf Dialog erweitern, indem eine Überprüfung von alert.getDialogPane().isFocused() innerhalb der isAlertFocused(Alert alert) Methode hinzufügen, aber das ist aus der Umfang meiner Frage.