JavaFX 使用自定义对象编辑 TreeView
JavaFX Editing TreeView with custom object
我需要使 TreeView 可编辑,并且 TreeView 具有通用类型的 TreeItem Content
。
我通过覆盖 Content
class 中的 toString()
设法在 TreeView 上显示我的对象。但是,即使我知道自定义编辑功能与 CellFactory 有关系,我还是无法使用它。
我想要实现的编辑如下所示:
- 当我通过双击或按 Enter 键开始编辑单元格时,会显示一个 TextField。
- 如果用户完成编辑后单元格中有':'分隔符,则将前者和后者分别保存在
name
和description
中 class Property
扩展 Content
.
- 如果没有,在扩展
Content
. 的classConcept
中保存name
的内容
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;
}
}
我如何对它们进行编码以创建有效的编辑功能?
-- 抱歉英语不好,我是留学生:(
以下应该适用于您的控制器。如果您使用 TextFieldTreeCell
,则无需自己处理编辑事件。
使用 toString()
来确定对象在 UI 中的显示方式也不是好的做法(它使用本质上实现部分视图的代码“污染”了数据模型;您可能并且很可能会希望 toString()
方法提供不同的信息,例如用于调试)。
所以像这样:
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");
}
}
我需要使 TreeView 可编辑,并且 TreeView 具有通用类型的 TreeItem Content
。
我通过覆盖 Content
class 中的 toString()
设法在 TreeView 上显示我的对象。但是,即使我知道自定义编辑功能与 CellFactory 有关系,我还是无法使用它。
我想要实现的编辑如下所示:
- 当我通过双击或按 Enter 键开始编辑单元格时,会显示一个 TextField。
- 如果用户完成编辑后单元格中有':'分隔符,则将前者和后者分别保存在
name
和description
中 classProperty
扩展Content
. - 如果没有,在扩展
Content
. 的class
Concept
中保存name
的内容
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;
}
}
我如何对它们进行编码以创建有效的编辑功能?
-- 抱歉英语不好,我是留学生:(
以下应该适用于您的控制器。如果您使用 TextFieldTreeCell
,则无需自己处理编辑事件。
使用 toString()
来确定对象在 UI 中的显示方式也不是好的做法(它使用本质上实现部分视图的代码“污染”了数据模型;您可能并且很可能会希望 toString()
方法提供不同的信息,例如用于调试)。
所以像这样:
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");
}
}