可以将java.lang.reflect.Field发布到javafx.scene.control.TextField吗?

时间:2017-05-04 14:50:33

标签: javafx-8

可以将java.lang.reflect.Field发布到javafx.scene.control.TextField吗?

例如:

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

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

2 个答案:

答案 0 :(得分:1)

如果要修改TextField,则需要从这些字段中检索值(并将此值转换为TextField)。

以下示例应演示该方法:

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

答案 1 :(得分:0)

反思可能是一个非常糟糕的方法。在许多问题中,您使功能依赖于代码的编写方式。具体来说,您假设每个文本字段都存储在某个类的特定实例字段中。如果您更改了实施,例如因此,您将文本字段保留在数据结构中而不是自己维护对它们的引用,那么您的功能将会中断。由于显而易见的原因,编写与代码的实际实现紧密耦合的代码是不好的做法。

一种更好的方法就是将所有文本字段放在一个列表(或其他数据结构)中,这样您就可以轻松地随意使用它们。 E.g。

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

另一种方法是使用CSS查找。如果myForm是某个节点,它是所有文本字段的祖先:

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

但请注意,CSS应用在CSS应用之后才会起作用(默认情况下,这意味着首次渲染场景后)。

另一种方法是,如果所有文本字段都包含在单个直接父级(例如第一个示例中的网格窗格)中,则将迭代子节点并过滤文本字段:

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