具有两列 JavaFX 8 的 TreeView
TreeView with Two Columns JavaFX 8
我需要在 JavaFX 8 中有一个可扩展的 nestable 键值列表。这在功能上类似于 TreeTableView
,但它是垂直定向的,而不是水平定向的。换句话说,行将是 headers 而不是 X-Y 倒轴 table 的列。由于 TreeTableView
是水平的限制,我开始探索 TreeView
的选项。 TreeView
效果很好,但只有一列我需要在每一行中有一个键值对。我真正需要的是如下所示:
请注意 foo
和 bar
可以是唯一的。
如何向 TreeView
添加第二列?
这是一个基于为 TreeView
创建行状单元格的自定义单元格工厂的想法。创建了一个自定义单元格,其中包含网格中的 2 个标签和一些调整大小行为设置。
public class CustomTree extends Application {
@Override
public void start(Stage stage) throws Exception {
TreeView<String[]> tree = new TreeView<>();
tree.setCellFactory(cell -> new TreeCell<String[]>() {
private GridPane pane = new GridPane();
private Label keyLabel = new Label();
private Label valueLabel = new Label();
private Border keyBorder = new Border(
new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, new BorderWidths(0.5, 0.5, 0.5, 1)));
private Border valueBorder = new Border(
new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, new BorderWidths(0.5, 1, 0.5, 0.5)));
{
pane.getChildren().addAll(keyLabel, valueLabel);
GridPane.setConstraints(keyLabel, 0, 0);
GridPane.setConstraints(valueLabel, 1, 0);
ColumnConstraints column1 = new ColumnConstraints();
column1.setPercentWidth(50);
ColumnConstraints column2 = new ColumnConstraints();
column2.setPercentWidth(50);
pane.getColumnConstraints().addAll(column1, column2);
keyLabel.setBorder(keyBorder);
valueLabel.setBorder(valueBorder);
keyLabel.setMaxWidth(Double.MAX_VALUE);
valueLabel.setMaxWidth(Double.MAX_VALUE);
setPadding(Insets.EMPTY);
}
@Override
public void updateItem(String[] name, boolean empty) {
super.updateItem(name, empty);
if (empty || name == null) {
setText(null);
setGraphic(null);
} else {
keyLabel.setText(name[0]);
valueLabel.setText(name[1]);
setGraphic(pane);
}
}
});
TreeItem<String[]> root = new TreeItem<>(new String[] { "", "" });
TreeItem<String[]> sub1 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub2 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub3 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub4 = new TreeItem<>(new String[] { "Foo", "" });
TreeItem<String[]> sub5 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub41 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub42 = new TreeItem<>(new String[] { "Foo", "Bar" });
root.getChildren().addAll(sub1, sub2, sub3, sub4, sub5);
sub4.getChildren().addAll(sub41, sub42);
tree.setRoot(root);
Scene scene = new Scene(tree);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
请注意,根也必须使用此单元格类型,尽管可以使用 tree.setShowRoot(false);
完全隐藏根。这种方法的两个缺点是每个单元格都作为一个单元运行 - 没有列的概念,并且单元格的值作为数组给出,因此失去了类型安全性。您可以自己扩展此示例。
使用(通用的)TableView
或 TreeTableView
方法是可能的,尽管需要做更多的工作。
我需要在 JavaFX 8 中有一个可扩展的 nestable 键值列表。这在功能上类似于 TreeTableView
,但它是垂直定向的,而不是水平定向的。换句话说,行将是 headers 而不是 X-Y 倒轴 table 的列。由于 TreeTableView
是水平的限制,我开始探索 TreeView
的选项。 TreeView
效果很好,但只有一列我需要在每一行中有一个键值对。我真正需要的是如下所示:
请注意 foo
和 bar
可以是唯一的。
如何向 TreeView
添加第二列?
这是一个基于为 TreeView
创建行状单元格的自定义单元格工厂的想法。创建了一个自定义单元格,其中包含网格中的 2 个标签和一些调整大小行为设置。
public class CustomTree extends Application {
@Override
public void start(Stage stage) throws Exception {
TreeView<String[]> tree = new TreeView<>();
tree.setCellFactory(cell -> new TreeCell<String[]>() {
private GridPane pane = new GridPane();
private Label keyLabel = new Label();
private Label valueLabel = new Label();
private Border keyBorder = new Border(
new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, new BorderWidths(0.5, 0.5, 0.5, 1)));
private Border valueBorder = new Border(
new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, new BorderWidths(0.5, 1, 0.5, 0.5)));
{
pane.getChildren().addAll(keyLabel, valueLabel);
GridPane.setConstraints(keyLabel, 0, 0);
GridPane.setConstraints(valueLabel, 1, 0);
ColumnConstraints column1 = new ColumnConstraints();
column1.setPercentWidth(50);
ColumnConstraints column2 = new ColumnConstraints();
column2.setPercentWidth(50);
pane.getColumnConstraints().addAll(column1, column2);
keyLabel.setBorder(keyBorder);
valueLabel.setBorder(valueBorder);
keyLabel.setMaxWidth(Double.MAX_VALUE);
valueLabel.setMaxWidth(Double.MAX_VALUE);
setPadding(Insets.EMPTY);
}
@Override
public void updateItem(String[] name, boolean empty) {
super.updateItem(name, empty);
if (empty || name == null) {
setText(null);
setGraphic(null);
} else {
keyLabel.setText(name[0]);
valueLabel.setText(name[1]);
setGraphic(pane);
}
}
});
TreeItem<String[]> root = new TreeItem<>(new String[] { "", "" });
TreeItem<String[]> sub1 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub2 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub3 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub4 = new TreeItem<>(new String[] { "Foo", "" });
TreeItem<String[]> sub5 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub41 = new TreeItem<>(new String[] { "Foo", "Bar" });
TreeItem<String[]> sub42 = new TreeItem<>(new String[] { "Foo", "Bar" });
root.getChildren().addAll(sub1, sub2, sub3, sub4, sub5);
sub4.getChildren().addAll(sub41, sub42);
tree.setRoot(root);
Scene scene = new Scene(tree);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
请注意,根也必须使用此单元格类型,尽管可以使用 tree.setShowRoot(false);
完全隐藏根。这种方法的两个缺点是每个单元格都作为一个单元运行 - 没有列的概念,并且单元格的值作为数组给出,因此失去了类型安全性。您可以自己扩展此示例。
使用(通用的)TableView
或 TreeTableView
方法是可能的,尽管需要做更多的工作。