2017-05-04 1 views
-1

Il est possible d'émettre java.lang.reflect.Field à javafx.scene.control.TextField?Il est possible d'émettre java.lang.reflect.Field à javafx.scene.control.TextField?

Par exemple:

Field[] nodes; 
nodes = clase.getDeclaredFields(); 

for (Field n : nodes) 
    if (n.getType().getSimpleName().equals("TextField")) 
    ((TextField)((Object) n)).setText("Text"); 
+0

Non: un 'Field' n'est pas un' TextField', et ne peut jamais l'être. (Il peut être de type 'TextField', mais cela ne veut pas dire la même chose.) Qu'essayez-vous vraiment de faire? –

+0

Je sais qu'un Champ n'est pas un TextField. J'essaye d'obtenir tout le TextField d'un formulaire pour modifier une certaine propriété, de sorte que j'essaye de le faire avec Reflection obtenant tout le TextField déclaré dans la classe. – R3ing

+0

Si vous le savez déjà, pourquoi publiez-vous du code où vous essayez de transformer un 'Field' en un' TextField'? Vous savez qu'il est garanti de lancer une 'ClassCastException'. Pourquoi utiliser la réflexion du tout ici? Pourquoi n'appeleriez-vous pas simplement la méthode sur chaque champ de texte dans le contrôleur, de la manière habituelle? Vous devez [modifier] votre question pour expliquer le problème réel. –

Répondre

1

Si vous souhaitez modifier les TextField s, vous devez récupérer la valeur de ces champs (et jeter cette valeur à TextField).

L'exemple suivant doit démontrer l'approche:

private TextField t1 = new TextField(); 
private TextField t2 = new TextField(); 

@Override 
public void start(Stage primaryStage) { 
    Button btn = new Button("Say 'Hello World'"); 
    btn.setOnAction((ActionEvent event) -> { 
     Object object = this; 
     Class clazz = object.getClass(); 
     for (Field field : clazz.getDeclaredFields()) { 
      if (field.getType().getName().equals("javafx.scene.control.TextField")) { 
       try { 
        // get field value here 
        TextField textField = (TextField) field.get(object); 

        if (textField != null) { 
         textField.setText("Hello World"); 
        } 
       } catch (IllegalArgumentException | IllegalAccessException ex) { 
        Logger.getLogger(ReflectTest.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 
     } 

    }); 

    VBox root = new VBox(); 
    root.getChildren().addAll(btn, t1, t2); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
+0

Merci beaucoup. James_D m'a dit que j'étais fou et que tu ne pouvais pas faire ça, convertis un java.lang.reflect.Field en javafx.scene.control.TextField. Encore merci beaucoup. – R3ing

+0

@ R3ing J'ai dit que vous ne pouviez pas assigner 'Field' à' TextField': vous ne pouvez pas - vous devez en extraire la valeur comme dans cette réponse. Mais j'ai soutenu (et argumente toujours) qu'il n'y a aucun intérêt dans cette approche: s'il y a tellement de champs de texte qu'une approche comme celle-ci vaut la peine d'être considérée, alors vous ne voulez probablement pas tous les déclarer individuellement comme champs. –

0

La réflexion est probablement une approche vraiment mauvais à cela. Parmi de nombreux problèmes est que vous faites la fonctionnalité dépend de comment le code est écrit. Plus précisément, vous supposez que chaque champ de texte est stocké dans un champ d'instance spécifique dans une classe. Si vous modifiez l'implémentation, par ex. afin que vous gardiez les champs de texte dans une structure de données au lieu d'y maintenir vous-même des références, alors votre fonctionnalité se cassera. C'est une mauvaise pratique d'écrire du code qui est si étroitement lié à l'implémentation réelle du code, pour des raisons évidentes. Une meilleure approche consisterait simplement à placer tous les champs de texte dans une liste (ou une autre structure de données), de sorte que vous puissiez facilement faire ce dont vous avez besoin. Par exemple.

public class MyForm { 

    private GridPane view ; 

    private String[] messages = {"First name:", "Last name", "Email"} ; 

    private List<TextField> textFields ; 

    public MyForm { 

     view = new GridPane(); 
     textFields = new ArrayList<>(); 

     for (int r = 0; r < messages.length ; r++) { 
      view.addRow(r, new Label(messages[r]), createTextField(messages[r])); 
     } 
    } 

    private TextField createTextField(String text) { 
     TextField textField = new TextField(); 
     textField.setPromptText(text); 
     textFields.add(textField); 
     return textField ; 
    } 

    public void processTextFields() { 
     textField.forEach(tf -> tf.setText("Hello")); 
    } 
} 

Une autre approche serait d'utiliser une recherche CSS. Si myForm est un nœud qui est un ancêtre de tous les champs de texte:

myForm.lookupAll(".text-field").forEach(node -> { 
    TextField textField = (TextField)node ; 
    textField.setText("Hello"); 
}); 

mais notez que les recherches CSS ne fonctionnera pas qu'après CSS a été appliqué (par défaut, cela signifie après la scène a été rendu pour la première fois).

Une autre façon, si tous les champs de texte sont tous contenus dans un seul parent direct (tel que le panneau de grille dans le premier exemple), serait d'effectuer une itération dans les nœuds enfants et filtrer les champs de texte:

textFieldParentNode.getChildrenUnmodifiable().stream() 
    .filter(TextField.class::isInstance) 
    .map(TextField.class::cast) 
    .forEach(tf -> tf.setText("Hello"));