我正在尝试编辑 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();
}
}
编辑并提交值时,
如果TreeView
和TreeItem
通用类型是 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
不存储任何可识别的信息,这是您可以拥有的最好的信息)并将显示 String
从 toString()
获得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/