Reputation: 163
I need to make TreeView editable, and the TreeView has TreeItem with a generic type Content
.
I managed to display my objects on TreeView by overriding toString()
in the Content
class. However, even though I know the custom editing feature has something to do with CellFactory, I couldn't get it to work.
The editing I wanted to implement works like below:
name
and description
in the class Property
which extends Content
.name
in the class Concept
which extends Content
.MainController.java
package jsh.hiercards;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTreeView;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.input.KeyEvent;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@FXML
public JFXTreeView<Content> treeView;
@Override
public void initialize(URL location, ResourceBundle resources) {
TreeItem<Content> root = new TreeItem<>(new Concept("TESTROOT", null));
root.getChildren().add(new TreeItem<>(new Concept("TESTCONCEPT", (Concept) root.getValue())));
root.getChildren().add(new TreeItem<>(new Property("TESTPROPERTY", (Concept) root.getValue(), "DESCRIPTION")));
treeView.setRoot(root);
}
@FXML
public void startEdit(TreeView.EditEvent e) {
System.out.println("Start");
}
@FXML
public void commitEdit(TreeView.EditEvent e) {
System.out.println("Commit");
}
@FXML
public void cancelEdit(TreeView.EditEvent e) {
System.out.println("Cancel");
}
@FXML
public void typeHandle(KeyEvent e) {
System.out.println("Type");
}
}
Content.java
package jsh.hiercards;
import javafx.scene.control.TreeItem;
public abstract class Content {
public String name;
public Concept parent;
private Content() {
}
public Content(String name, Concept parent) {
this.name = name;
this.parent = parent;
}
public abstract String toString();
}
Concept.java
package jsh.hiercards;
import javafx.scene.control.TreeItem;
public class Concept extends Content {
public Concept(String name, Concept parent) {
super(name, parent);
}
@Override
public String toString() {
return name;
}
}
Property.java
package jsh.hiercards;
import javafx.scene.control.TreeItem;
public class Property extends Content {
public String description;
public Property(String name, Concept parent, String description) {
super(name, parent);
this.description = description;
}
@Override
public String toString() {
return name + " : " + description;
}
}
How can I code them to make a editing feature which works?
-- Sorry for poor English, I'm a foreign student :(
Upvotes: 1
Views: 985
Reputation: 209319
The following should work for your controller. If you use a TextFieldTreeCell
there is no need to handle the edit events yourself.
It's also not good practice to use toString()
to determine how an object is displayed in the UI (it "pollutes" the data model with code that is essentially implementing part of the view; you may, and probably will, want the toString()
method to provide different information, e.g. for debugging).
So something like:
package jsh.hiercards;
public abstract class Content {
private String name;
private Concept parent;
private Content() {
}
public Content(String name, Concept parent) {
this.name = name;
this.parent = parent;
}
public String getName() {
return name ;
}
public Concept getParent() {
return parent ;
}
}
package jsh.hiercards;
public class Concept extends Content {
public Concept(String name, Concept parent) {
super(name, parent);
}
}
package jsh.hiercards;
public class Property extends Content {
private String description;
public Property(String name, Concept parent, String description) {
super(name, parent);
this.description = description;
}
public String getDescription() {
return description ;
}
}
package jsh.hiercards;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTreeView;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.input.KeyEvent;
import javafx.util.StringConverter ;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@FXML
public JFXTreeView<Content> treeView;
@Override
public void initialize(URL location, ResourceBundle resources) {
treeView.setCellFactory(tv -> new TextFieldTreeCell<>(new StringConverter<>() {
@Override
public Content fromString(String text) {
TreeItem<Content> parentItem = getTreeItem().getParent();
Content parent = parentItem == null ? null : parentItem.getValue() ;
String[] tokens = text.split(":", 2);
if (tokens.length < 2) {
return new Concept(tokens[0], parent);
} else return new Property(tokens[0], parent, tokens[1]);
}
@Override
public String toString(Content content) {
if (content instanceof Property property) {
return property.getName() + " : " + property.getDescription();
}
return content.getName();
}
}));
TreeItem<Content> root = new TreeItem<>(new Concept("TESTROOT", null));
root.getChildren().add(new TreeItem<>(new Concept("TESTCONCEPT", (Concept) root.getValue())));
root.getChildren().add(new TreeItem<>(new Property("TESTPROPERTY", (Concept) root.getValue(), "DESCRIPTION")));
treeView.setRoot(root);
}
/*
@FXML
public void startEdit(TreeView.EditEvent e) {
System.out.println("Start");
}
@FXML
public void commitEdit(TreeView.EditEvent e) {
System.out.println("Commit");
}
@FXML
public void cancelEdit(TreeView.EditEvent e) {
System.out.println("Cancel");
}
*/
@FXML
public void typeHandle(KeyEvent e) {
System.out.println("Type");
}
}
Upvotes: 2