Issue
I am trying to edit a TreeView
item, below is my code,
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();
}
}
While editing and commit the value,
If the TreeView
and TreeItem
generic types are String
i have used
return new TextFieldTreeCell<String>(new DefaultStringConverter());
When I use Object
, i am not sure how to use String converter which leads to ,
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.
How can i mitigate this exception.
Solution
Displaying Object
instances in a TreeView
does not really make sense as they do not store any information to display.
Practically, the following StringConverter
helps you to remove the error:
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();
}
});
}
});
What it does: It defines a StringConverter
which will return a new Object
instance from any string typed into the TextField
on commit (as the Object
does not store any information to identify, this is the best you can have) and will display the String
got from the toString()
method of the Object
instance.
But: You should provide a data model for the TreeView
to display, which is capable to store at least the textual data that could be displayed.
I have updated your code to create an example of a TreeView
backed by a really simple data model:
It defines the data model for the tree (Item
class) which class has one single property to the the name of the item. The generic parameter of the TreeView
is set to this Item
class, therefore the TreeView
is capable to display Item
instances.
As you can see I have defined a StringConverter
also, which now makes much more sense: the fromString
method is executed when the typed text is commited, in this case the method will return a new Item
instance, that has its name set to the input String. The toString
method is needed to specify, how to textually display an Item
instance. In our case we will return the name of the particular instance.
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);
}
}
Answered By - DVarga
Answer Checked By - Cary Denson (JavaFixing Admin)