JavaFX TreeView编辑项目

标签 java javafx treeview

我正在尝试编辑 TreeView项目,下面是我的代码,

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.*;

public class TreeViewSample extends Application {

    public static void main(String[] args) {
        launch(args);
    }
    TreeView<Object> tree;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Tree View Sample");

        TreeItem<Object> rootItem = new TreeItem<Object>("Tree");
        rootItem.setExpanded(true);
        for (int i = 1; i < 6; i++) {
            TreeItem<Object> item = new TreeItem<Object>("Item" + i);
            rootItem.getChildren().add(item);
        }

        ContextMenu menu = new ContextMenu();
        MenuItem renameItem = new MenuItem("Rename");
        menu.getItems().add(renameItem);

        tree = new TreeView<Object>(rootItem);
        tree.setContextMenu(menu);
        tree.setEditable(true);

        tree.setCellFactory(new Callback<TreeView<Object>, TreeCell<Object>>() {
            @Override
            public TreeCell<Object> call(TreeView<Object> p) {
                return new TextFieldTreeCell<Object>();
            }
        });
        renameItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                tree.edit(tree.getSelectionModel().getSelectedItem());
            }
        });

        tree.setOnEditCommit(new EventHandler<TreeView.EditEvent<Object>>() {
            @Override
            public void handle(TreeView.EditEvent<Object> event) {
                System.out.println("Commit Value");
            }
        });
        StackPane root = new StackPane();
        root.getChildren().add(tree);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

编辑并提交值时,

如果TreeViewTreeItem通用类型是 String我用过 return new TextFieldTreeCell<String>(new DefaultStringConverter());

当我使用Object时,我不知道如何使用字符串转换器,这会导致,

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: 
Attempting to convert text input into Object, but provided StringConverter is null. Be sure to set a StringConverter in your cell factory.

如何缓解此异常。

最佳答案

显示Object TreeView 中的实例并没有真正的意义,因为它们不存储任何要显示的信息。

实际上,以下 StringConverter帮助您消除错误:

tree.setCellFactory(new Callback<TreeView<Object>, TreeCell<Object>>() {
    @Override
    public TreeCell<Object> call(TreeView<Object> p) {
        return new TextFieldTreeCell<Object>(new StringConverter<Object>(){

            @Override
            public String toString(Object object) {
                return object.toString();
            }

            @Override
            public Object fromString(String string) {
                return new Object();
            }
        });
    }
});

它的作用:它定义了 StringConverter这将返回一个新的 Object 来自输入到 TextField 的任何字符串的实例提交时(因为 Object 不存储任何可识别的信息,这是您可以拥有的最好的信息)并将显示 StringtoString() 获得Object的方法实例。

但是:您应该为TreeView提供一个数据模型。显示,至少能够存储可以显示的文本数据。

我已更新您的代码以创建 TreeView示例由一个非常简单的数据模型支持:

它定义了树( Item 类)的数据模型,该类具有与项目名称相关的单个属性。 TreeView 的通用参数设置为 Item类,因此 TreeView能够显示Item实例。

如你所见,我定义了一个 StringConverter另外,现在更有意义了:fromString提交键入的文本时执行方法,在这种情况下该方法将返回一个新的 Item实例,其名称设置为输入字符串。 toString需要方法来指定如何以文本方式显示 Item实例。在我们的例子中,我们将返回特定实例的名称。

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.*;

public class TreeViewSample2 extends Application {

    public static void main(String[] args) {
        launch(args);
    }
    TreeView<Item> tree;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Tree View Sample");

        TreeItem<Item> rootItem = new TreeItem<Item>(new Item("Root"));


        rootItem.setExpanded(true);
        for (int i = 1; i < 6; i++) {
            TreeItem<Item> item = new TreeItem<Item>(new Item("Item"+i));
            rootItem.getChildren().add(item);
        }

        ContextMenu menu = new ContextMenu();
        MenuItem renameItem = new MenuItem("Rename");
        menu.getItems().add(renameItem);

        tree = new TreeView<Item>(rootItem);
        tree.setContextMenu(menu);
        tree.setEditable(true);

        tree.setCellFactory(new Callback<TreeView<Item>, TreeCell<Item>>() {
            @Override
            public TreeCell<Item> call(TreeView<Item> p) {
                return new TextFieldTreeCell<Item>(new StringConverter<Item>(){

                    @Override
                    public String toString(Item object) {
                        return object.getName();
                    }

                    @Override
                    public Item fromString(String string) {
                        return new Item(string);
                    }
                });
            }
        });
        renameItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                tree.edit(tree.getSelectionModel().getSelectedItem());
            }
        });

        tree.setOnEditCommit(new EventHandler<TreeView.EditEvent<Item>>() {
            @Override
            public void handle(TreeView.EditEvent<Item> event) {
                System.out.println("Commit Value");
            }
        });
        StackPane root = new StackPane();
        root.getChildren().add(tree);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

class Item {
    private SimpleStringProperty name = new SimpleStringProperty("");
    public SimpleStringProperty nameProperty() {
        return name;
    }

    public final String getName() { return nameProperty().get();}
    public final void setName(String newName) { nameProperty().set(newName);}

    public Item(String name) {
        setName(name);
    }
}

关于JavaFX TreeView编辑项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39465985/

相关文章:

c# - 如何使用 Xaml 将列表绑定(bind)到 WPF TreeView ?

asp.net - 如何在 JavaScript 中找到 ASP.NET TreeView 节点的父节点?

Java Unicode 到可读文本的转换解码

java - 使用对象类型引用调用函数(持有不同的实例)

java - 如何在正则表达式中表示固定数量的重复?

JavaFX- float 菜单

java - 如何在JavaFX中支持macOS字符输入

java - 使用 JavaFX FXML 在 CSS 中设计布局 Pane 而不创建变量?

wpf - 选择 TreeView 项后如何启用按钮?

Java,仅对同步块(synchronized block)中的变量或所有实例变量发生与主内存的同步?