当前位置: 首页 > 知识库问答 >
问题:

从TextField更新TreeView项

黄永怡
2023-03-14
selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));

我认为这个解决方案是非常愚蠢的,必须有一个方法如何编码它更好。我不能每次都创建一个新的Person实例,这对我来说是不可接受的。

我也尝试为treeView触发一个事件,但这种方法会破坏焦点,也是一个愚蠢的解决方案。我也找到了这样的解决办法:

treeView.getRoot().getChildren().set(treeView.getSelectionModel().getSelectedIndex(), new TreeItem<MainAppTF.Person>(updatedPerson));

这也是不好的解决办法。

public class MainAppTF extends Application {

    private TreeView<Person> treeView;
    private final TreeItem<Person> rootNode = new TreeItem<Person>(new Person("Root", 0));

    private TextField textField;

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 400, 400);

        treeView = new TreeView<Person>(rootNode);
        treeView.setShowRoot(false);
        rootNode.setExpanded(true);

        List<TreeItem<Person>> list = new ArrayList<>();
        list.add(new TreeItem<Person>(new Person("Adam", 20)));
        list.add(new TreeItem<Person>(new Person("Eva", 19)));
        list.add(new TreeItem<Person>(new Person("Carl", 30)));
        rootNode.getChildren().setAll(list);

        textField = new TextField("");

        attachListeners();

        box.getChildren().add(treeView);
        box.getChildren().add(textField);
        VBox.setMargin(treeView, new Insets(10));
        VBox.setMargin(textField, new Insets(10));

        stage.setScene(scene);
        stage.show();
    }

    private void attachListeners() {
        treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<Person>>() {
            @Override
            public void changed(ObservableValue<? extends TreeItem<Person>> observable, TreeItem<Person> oldValue, TreeItem<Person> newValue) {
                textField.setText(newValue.getValue().getName());
            }
        });

        textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    updateTreeViewItem();
                }
            }
        });

        textField.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                updateTreeViewItem();
            }
        });
    }

    private void updateTreeViewItem() {
        TreeItem<Person> selectedItem = treeView.getSelectionModel().getSelectedItem();
        Person selectedPerson = selectedItem.getValue();
        selectedPerson.nameProperty().set(textField.getText());

        // FIXME This is silly! There must be another way!
        selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    private class Person {

        private StringProperty name;
        private int age;

        public Person() {
            this(null, 0);
        }

        public Person(String name, int age) {
            this.name = new SimpleStringProperty(name);
            this.age = age;
        }

        public StringProperty nameProperty() {
            return name;
        }

        public String getName() {
            return name.getValue();
        }

        public void setName(String name) {
            this.name.setValue(name);
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return getName() + " - " + getAge();
        }

    }

}

共有1个答案

濮阳征
2023-03-14

TreeItem包装的人员的名称更改时,您希望TreeModificationEvent接收TreeModificationEvent。

可以通过将侦听器附加到person的nameProperty()来实现这一点,然后触发适当的事件:

TreeItem<Person> treeItem = new TreeItem<>(person);
ChangeListener<String> nameListener = (obs, oldName, newName) -> {
    TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
    Event.fireEvent(treeItem, event);
};
person.nameProperty().addListener(nameListener);

如果有可能更改TreeItem(TreeItem.setValue(new Person(...)))包装的值,那么您需要确保从旧的Person中删除监听器并将其添加到新的Person中。因此,谨慎的做法可能是:

treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
    if (oldValue != null) {
        oldValue.nameProperty().removeListener(nameListener);
    }
    if (newValue != null) {
        newValue.nameProperty().addListener(nameListener);
    }
});
private TreeItem<Person> createTreeItem(Person person) {
    TreeItem<Person> treeItem = new TreeItem<>(person);
    ChangeListener<String> nameListener = (obs, oldName, newName) -> {
        TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
        Event.fireEvent(treeItem, event);
    };
    person.nameProperty().addListener(nameListener);
    treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
        if (oldValue != null) {
            oldValue.nameProperty().removeListener(nameListener);
        }
        if (newValue != null) {
            newValue.nameProperty().addListener(nameListener);
        }
    });
    return treeItem ;
}

然后做

list.add(createTreeItem(new Person("Adam", 20)));
list.add(createTreeItem(new Person("Eva", 19)));
list.add(createTreeItem(new Person("Carl", 30)));

也可以创建TreeItem 的子类:

private class PersonTreeItem extends TreeItem<Person> {

    private ChangeListener<String> nameListener = (obs, oldName, newName) -> {
        TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), this);
        Event.fireEvent(this, event);
    };

    public PersonTreeItem(Person person) {
        super(person);
        person.nameProperty().addListener(nameListener);
        this.valueProperty().addListener((obs, oldValue, newValue) -> {
            if (oldValue != null) {
                oldValue.nameProperty().removeListener(nameListener);
            }
            if (newValue != null) {
                newValue.nameProperty().addListener(nameListener);
            }
        });
    }
}

并且做

list.add(new PersonTreeItem(new Person("Adam", 20)));
list.add(new PersonTreeItem(new Person("Eva", 19)));
list.add(new PersonTreeItem(new Person("Carl", 30)));
import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeItem.TreeModificationEvent;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MainAppTF extends Application {

    private TreeView<Person> treeView;
    private final TreeItem<Person> rootNode = new TreeItem<Person>(new Person("Root", 0));

    private TextField textField;

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 400, 400);

        treeView = new TreeView<Person>(rootNode);
        treeView.setShowRoot(false);
        rootNode.setExpanded(true);

        List<TreeItem<Person>> list = new ArrayList<>();
        list.add(createTreeItem(new Person("Adam", 20)));
        list.add(createTreeItem(new Person("Eva", 19)));
        list.add(createTreeItem(new Person("Carl", 30)));
        rootNode.getChildren().setAll(list);

        textField = new TextField("");

        attachListeners();

        box.getChildren().add(treeView);
        box.getChildren().add(textField);
        VBox.setMargin(treeView, new Insets(10));
        VBox.setMargin(textField, new Insets(10));

        stage.setScene(scene);
        stage.show();
    }

    private void attachListeners() {
        treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<Person>>() {
            @Override
            public void changed(ObservableValue<? extends TreeItem<Person>> observable, TreeItem<Person> oldValue, TreeItem<Person> newValue) {
                textField.setText(newValue.getValue().getName());
            }
        });

        textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    updateTreeViewItem();
                }
            }
        });

        textField.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                updateTreeViewItem();
            }
        });
    }

    private void updateTreeViewItem() {
        TreeItem<Person> selectedItem = treeView.getSelectionModel().getSelectedItem();
        Person selectedPerson = selectedItem.getValue();
        selectedPerson.nameProperty().set(textField.getText());

        // FIXME This is silly! There must be another way!
//        selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));
    }

    public static void main(String[] args) {
        Application.launch(args);
    }


    private TreeItem<Person> createTreeItem(Person person) {
        TreeItem<Person> treeItem = new TreeItem<>(person);
        ChangeListener<String> nameListener = (obs, oldName, newName) -> {
            TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
            Event.fireEvent(treeItem, event);
        };
        person.nameProperty().addListener(nameListener);
        treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
            if (oldValue != null) {
                oldValue.nameProperty().removeListener(nameListener);
            }
            if (newValue != null) {
                newValue.nameProperty().addListener(nameListener);
            }
        });
        return treeItem ;
    }

    private class Person {

        private StringProperty name;
        private int age;

        public Person() {
            this(null, 0);
        }

        public Person(String name, int age) {
            this.name = new SimpleStringProperty(name);
            this.age = age;
        }

        public StringProperty nameProperty() {
            return name;
        }

        public String getName() {
            return name.getValue();
        }

        public void setName(String name) {
            this.name.setValue(name);
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return getName() + " - " + getAge();
        }

    }

}

 类似资料:
  • 我有1个“viewelements”-类,1个控制器和1个fxml-文件。 ViewElements-Class包含FXML的元素,如按钮和文本字段。Controller-Class包含业务逻辑。 我试图更新文本字段“TextFieldDateIausWaeHlen”,我想将文件的路径设置到文本字段中,但我的方法不起作用。 我的错误在哪里?

  • 我有一个目标,它有一个目标清单。一个目标有一系列的策略。一个战略有一个战术清单。战术有一个任务列表。 我希望能够在树视图中显示这一点,我希望树与项目同步。也就是说,如果我删除一个目标,该目标及其子目标也将从TreeView中消失。 计划是创建一个包装PlanItem的TreeItem。然后,将TreeItem的子TreeItems与PlanItem的子PlanItems同步。对于每个嵌套的Plan

  • 我已经扩展了TreeCell和TreeItem类。MyTreeItem包含一个自定义属性,我在MyTreeCell中使用它来渲染图形/字体等。问题是当我设置MyTreeCell.custom属性我不知道如何使TreeView/单元格重绘。 例如: 任何关于解决方案或(缺乏)设计方法的意见都受到赞赏。

  • 在选择我的treeview时遇到问题。其思想是,用户单击该项,然后将数据添加到他们选择的节点下 似乎所选项目是一个文本块,我似乎找不到一种方法将其作为treeview项目来添加节点。 是的,我对这种编程很陌生。 感谢您提供的任何帮助。

  • 树细胞是定制的,它看起来像下图。 在右侧,我选择了一棵树单元格或树项目。正如您所看到的,每个单元格的左侧都有手的图像视图。默认情况下,它是黑色的,但我想用白色图标替换它。如上所述。 我希望所有的文本和图像视图图标在选择改变为白色。和最后选择的树单元格回到正常的黑色。 我的树细胞代码如下。 问题是正确选择并添加了新的白色图标,但如何将上一个选定树项目的图像视图改回黑色图标。实际上,我有两张相同类型的

  • Treeview小部件显示实现gtk.TreeModel接口的模型的内容。 PyGTK提供以下类型的模型 - gtk.ListStore gtk.TreeStore gtk.TreeModelSort ListStore是一个列表模型。 与gtk.TreeView小部件关联时,它会生成一个包含要从中选择的项的列表框。 使用以下语法声明gtk.ListStore对象 - store = gtk.Li