2017-05-04 2 views
-1

Es ist möglich, java.lang.reflect.Field an javafx.scene.control.TextField auszustellen?Es ist möglich java.lang.reflect.Field auf javafx.scene.control.TextField auszugeben?

Zum Beispiel:

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

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

Nein: Ein 'Feld' ist kein' TextFeld' und kann niemals sein. (Es kann vom Typ TextField sein, aber das bedeutet nicht dasselbe.) Was versuchst du eigentlich zu tun? –

+0

Ich weiß, dass ein Feld kein TextField ist. Ich versuche, alle TextField eines Formulars zu erhalten, um eine Eigenschaft zu ändern, so dass ich versuche, es mit Reflection zu tun, die alle TextField in der Klasse deklariert. – R3ing

+0

Wenn Sie das bereits wissen, warum veröffentlichen Sie Code, bei dem Sie versuchen, ein 'Field' in ein' TextField' zu verwandeln? Sie wissen, dass es garantiert ist, eine 'ClassCastException' zu werfen. Warum hier überhaupt Reflexion? Warum sollten Sie die Methode nicht wie üblich auf jedem Textfeld im Controller aufrufen? Sie müssen Ihre Frage bearbeiten, um zu erklären, was das eigentliche Problem ist. –

Antwort

1

Wenn Sie die TextField s ändern möchten, müssen Sie den Wert aus diesen Feldern abzurufen (und werfen diesen Wert auf TextField).

Das folgende Beispiel soll den Ansatz zeigen:

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

Vielen Dank. James_D sagte mir, dass ich verrückt sei und dass du das niemals tun könntest, wandle ein java.lang.reflect.Field in javafx.scene.control.TextField um. Danke dir nochmal. – R3ing

+0

@ R3ing Ich sagte, Sie könnten einem 'TextField' kein' Field' zuweisen: Sie können nicht - Sie müssen den Wert von ihm wie in dieser Antwort abrufen. Aber ich argumentierte (und streite immer noch), dass dieser Ansatz keinen Sinn hat: Wenn es so viele Textfelder gibt, dass ein solcher Ansatz in Betracht gezogen werden kann, dann wollen Sie vermutlich nicht alle einzeln als Felder deklarieren. –

0

Reflexion ist wahrscheinlich ein wirklich schlechter Ansatz dazu. Unter vielen Problemen ist, dass Sie die Funktionalität von abhängig machen, wie der Code geschrieben wird. Insbesondere nehmen Sie an, dass jedes Textfeld in einem bestimmten Instanzfeld in einer Klasse gespeichert ist. Wenn Sie die Implementierung ändern, z. Damit Sie die Textfelder in einer Datenstruktur beibehalten, anstatt die Verweise auf sie selbst zu verwalten, wird Ihre Funktionalität unterbrochen. Es ist eine schlechte Praxis, aus offensichtlichen Gründen Code zu schreiben, der so eng an die tatsächliche Implementierung des Codes gekoppelt ist.

Ein besserer Ansatz wäre einfach, alle Textfelder in eine Liste (oder eine andere Datenstruktur) zu stellen, so dass Sie einfach alles tun können, was Sie brauchen. Z.B.

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

Ein anderer Ansatz wäre, eine CSS-Suche zu verwenden. Wenn myForm einige Knoten ist, dass ein Vorfahre aller Textfelder ist:

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

aber beachten Sie, dass CSS-Lookups wird erst funktionieren, nachdem CSS angewendet wurde (standardmäßig bedeutet dies, nachdem die Szene für die gemacht wurde erstes Mal).

Ein anderer Weg, wenn alle Textfelder in einem einzigen direkten parent (wie beispielsweise die Gitterscheibe in dem ersten Beispiel) enthalten sind, würde durch die untergeordneten Knoten iterieren und die Textfelder filtern:

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