【问题标题】:Introspection (JavaFx)内省 (JavaFx)
【发布时间】:2018-11-03 00:37:17
【问题描述】:

在进行了很多搜索之后,我把它留给你。 这是在我的应用程序 JavaFx 中,我使用内省自动生成一个 gridPane(然后我将其插入到对话框中)。因此,我有 TableView,当用户双击上面时,它会生成包含此 TableView 列的对话框。 在此对话框中,因此有允许修改 TableView 中字段值的 TextFields。 但是,我无法通过自省取回我的属性值,以及如何取回由于自省而创建的 textFields 的值? 有我的自省方法:

    public static  GridPane analyserChamp(Etudiant etu) {
    List<String> list = new ArrayList<>();
    Class<? extends Etudiant> classPixel = etu.getClass();
    Field attribut[] = classPixel.getDeclaredFields();
    GridPane gp = new GridPane();

    int i=0;
    for(Field p : attribut) {
        list.add(p.getName());
        Label lab = new Label();

        if(!p.getName().equals("classe")) {
            TextField l = new TextField();
            lab.setText(p.getName());
            gp.add(l, 1, i);

        }else {
            ComboBox<String> cb = new ComboBox<String>();
            cb.getItems().addAll("1Bi","2Bi","3Bi");
            gp.add(cb, 1, i);
        }

        gp.add(lab, 0, i);
        i++;

    }
    return gp;
}

这是我调用自省方法的代码:

                if(e.getClickCount() == 2) {
                Dialog<Etudiant> dialog = new Dialog<>();
                Etudiant test = tableViewEtudiant.getSelectionModel().getSelectedItems().get(0);

                if(test!=null) {

                    dialog.setTitle("Editor");
                    dialog.setHeaderText("You can update your question");
                    dialog.getDialogPane().setContent(Analysateur.analyserChamp(test));

                    ButtonType buttonCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
                    ButtonType buttonOk = new ButtonType("Ok", ButtonData.OK_DONE);
                    dialog.getDialogPane().getButtonTypes().addAll(buttonOk,buttonCancel);
                    //Confirmation of the edition
                    Optional<Etudiant> result = dialog.showAndWait();
                    //Edition  of the question in the gson file
                    GridPane tmp = Analysateur.analyserChamp(test);
                    if(result.isPresent()) {

                        // Here ?????

                    }

                }

提前致谢 ;)

【问题讨论】:

    标签: java javafx introspection


    【解决方案1】:

    解决这个问题的方法有很多,例如可以使用userData属性来存储属性的键,这样以后可以遍历GridPane子元素,获取Dialog中的每个值结果转换器。

    当你自省类Etudiant

    if(!p.getName().equals("classe")) {
                TextField l = new TextField();
                l.setUserData(p.getName()); //Store the attribute name in the TextField
                lab.setText(p.getName());
                gp.add(l, 1, i);
    
            }else {
                ComboBox<String> cb = new ComboBox<String>();
                cb.setUserData(p.getName()); //Store the attribute name in the ComboBox
                cb.getItems().addAll("1Bi","2Bi","3Bi");
                gp.add(cb, 1, i);
            }
    

    当你创建Dialog:

        Dialog<Etudiant> dialog = new Dialog<>();
        ...
        GridPane content = Analysateur.analyserChamp(test); //Keep the content accesible
        ...
        dialog.getDialogPane().setContent(content);
        ...
        dialog.setResultConverter(button -> { //Convert the result
            Etudiant result = new Etudiant();
            for (Node child : content.getChildren()) { //Iterate over the GridPane children
                if (child instanceof TextField) {
                    String attribute = ((TextField)child).getUserData();
                    String value = ((TextField)child).getTest();
                    //Set the value in the result attribute via instrospection
                }
                if (child instanceof ComboBox) {
                    //Do the same with combos
                }
            }
        });
    

    【讨论】:

    • 感谢您的回答。但是 l.setUserData(p.getName()) 不起作用,实际上 TextField 仍然是空的。当我得到文本字段的值时,也有空的。 (字符串属性 = ((TextField)child).getText();
    • 当我使用您的代码获取 TextField 的值时,他会在另一个类中获取 TextField 的值,在该类中我有我的 analyserChamp() 方法,而不是用户在对话框中输入的新值。
    • 然后您应该遍历实际内容:dialog.getDialogPane().getContent().getChildren() 以获取新值。
    【解决方案2】:

    存储Supplier 以获取Map&lt;Field, Supplier&lt;?&gt;&gt; 中字段的输入值。这样您就可以浏览地图的条目并检索分配的值:

    public class ReflectionDialog<T> extends Dialog<T> {
    
        public ReflectionDialog(Class<T> type, Supplier<T> factory) throws IllegalAccessException {
            GridPane gp = new GridPane();
            Field[] fields = type.getDeclaredFields();
    
            // stores getters for result value
            final Map<Field, Supplier<?>> results = new HashMap<>();
    
            int i = 0;
            for (Field field : fields) {
                if (String.class.equals(field.getType())) {
                    String name = field.getName();
                    Node input;
                    Supplier<?> getter;
                    if ("classe".equals(name)) {
                        ComboBox<String> cb = new ComboBox<>();
                        cb.getItems().addAll("1Bi", "2Bi", "3Bi");
                        getter = cb::getValue;
                        input = cb;
                    } else {
                        TextField l = new TextField();
                        getter = l::getText;
                        input = l;
                    }
                    results.put(field, getter);
                    gp.addRow(i, new Label(name), input);
                    i++;
                }
            }
    
            getDialogPane().setContent(gp);
            getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
            setResultConverter(buttonType -> {
                if (buttonType == ButtonType.OK) {
                    // create & initialize new object
                    final T object = factory.get();
                    results.forEach((k, v) -> {
                        try {
                            k.set(object, v.get());
                        } catch (IllegalAccessException ex) {
                            throw new IllegalStateException(ex);
                        }
                    });
                    return object;
                } else {
                    return null;
                }
            });
        }
    
    }
    
    public class A {
    
        String classe;
        String value;
    
        @Override
        public String toString() {
            return "A{" + "classe=" + classe + ", value=" + value + '}';
        }
    
    }
    
    ReflectionDialog<A> dialog = new ReflectionDialog<>(A.class, A::new);
    A result = dialog.showAndWait().orElse(null);
    System.out.println(result);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-21
      • 2014-01-06
      • 2016-03-13
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多