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

JavaFXTreeView编辑项

齐昊
2023-03-14

我正在尝试编辑一个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,则返回新的TextFieldTreeCell

当我使用Object时,我不知道如何使用String转换器,

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.

如何缓解此异常。

共有1个答案

章景同
2023-03-14

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

实际上,以下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();
            }
        });
    }
});

它的作用:它定义了一个StringConver,它将从提交时键入到TextField中的任何字符串返回一个新的Object实例(因为Object不存储任何要标识的信息,这是最好的你可以有),并将显示从Object实例的toString()方法获得的String

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

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

它定义了树(Itemclass)的数据模型,该树的类只有一个属性作为项的名称。TreeView的通用参数被设置为这个项目类,因此TreeView能够显示项目实例。

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

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 8中,我尝试在将新行添加到表中后编辑单元格,以优化用户体验。 选择了正确的行,但单元不会进入编辑模式。嗯,我很偶然地看到了这种情况,但很难再现。我做错了什么?

  •   复制 剪切 字符 y x 行 yy dd 需先在可视模式中选取 p 在光标后粘贴 P 在光标前粘贴 u 撤消 Ctrl+r 重做 Ctrl+y 逐字克隆上一行内容 Ctrl+e 逐字克隆下一行内容

  • 问题内容: 使用什么是能够编辑内容的最佳方法? 在我理想的情况下, 添加的 生日将是一个超链接,点击该链接将显示一个编辑表单-与带有更新按钮的当前添加表单相同。 实时预览(插播) HTML: App.js: 问题答案: 您应该将表单放在每个节点内,分别使用和启用和禁用编辑。像这样: 这里的关键点是: 我已将控件更改为本地范围 已添加到,因此我们可以在编辑时显示它 添加了带有的,以便在编辑时隐藏内容

  • Vim提供了许多命令,使编辑功能非常强大。 在本章中,将讨论以下主题内容 - 插入 附加 打开新行 替换 更改 更换 加入 1. 在光标前插入文本 要在光标之前插入文本执行以下步骤 - 打开Vim 切换到插入模式 在行的开头插入文本 假设位于行的中间,并且希望在当前行的开头插入文本,然后执行以下步骤 - 切换到命令模式 激活插入模式 此操作将光标移动到当前行的开头并在插入模式下切换Vim。 在光标

  • 概述 Sublime Text 有非常多的编辑功能,这里只能介绍一点皮毛。 多文本选择 多文本选择让你高效地修改文本,任何的赞美都无法形容它了,原因: 选择一些文本,按下Ctrl+D进行多选,如果想跳过当前项,按下Ctrl+K,Ctrl+D。 误选了按Ctrl+U撤销最后一次选中项。 多行选择合并成一行 Ctrl+L选中单行文本,Ctrl+Shift+L把多行选择变成单行选择的编辑状态。 列选择