为JavaFX treeTableView中的一级节点设置样式class
Setting a style class only for first-level nodes in JavaFX treeTableView
我有一个餐厅菜单,其中包含在 javaFX 中实现为 treeTableView 的菜肴和类别。
我想让类别行看起来与 CSS 不同,但我找不到过滤它们并应用 class 的方法。将图像向左移动一点也很好。我也没有运气使用 rowFactory。我看过但没看懂
这就是我填写 table 的方式。我省略了列和细胞工厂。
private void fillDishes(List<Dish> dishes){
root.getChildren().clear();
Map<String,TreeItem<Dish>> categoryMap = new HashMap<>();
for (Category c: allCats) {
TreeItem<Dish> newCat = new TreeItem<>(new Dish(c.getName(),null,null,null));
//newCat.getGraphic().getStyleClass().add("category");
categoryMap.put(c.getName(),newCat);
root.getChildren().add(newCat);
}
for (Dish d: dishes) {
categoryMap.get(d.getCategory()).getChildren().add(new TreeItem<>(d));
}
}
TreeTableView
使用 rowFactory
创建 TreeTableRow
。稍后它会将 TreeItem
分配给 TreeTableRow
。对于同一行,不同的 TreeItem
可能会再次发生这种情况。为此,您需要处理更改,这些更改可以通过将 ChangeHandler
添加到 TreeTableRow.treeItem
属性 来完成。如果将新的 TreeItem
分配给该行,您可以通过检查该行项的(不可见)根项的子项来检查顶级节点。
我更喜欢不需要搜索子列表的方法。可以将项目的父项与根进行比较。
public static class Item {
private final String value1;
private final String value2;
public Item(String value1, String value2) {
this.value1 = value1;
this.value2 = value2;
}
public String getValue1() {
return value1;
}
public String getValue2() {
return value2;
}
}
@Override
public void start(Stage primaryStage) {
final TreeItem<Item> root = new TreeItem<>(null);
TreeTableView<Item> ttv = new TreeTableView<>(root);
ttv.setShowRoot(false);
TreeTableColumn<Item, String> column1 = new TreeTableColumn<>();
column1.setCellValueFactory(new TreeItemPropertyValueFactory<>("value1"));
TreeTableColumn<Item, String> column2 = new TreeTableColumn<>();
column2.setCellValueFactory(new TreeItemPropertyValueFactory<>("value2"));
ttv.getColumns().addAll(column1, column2);
final PseudoClass topNode = PseudoClass.getPseudoClass("top-node");
ttv.setRowFactory(t -> {
final TreeTableRow<Item> row = new TreeTableRow<>();
// every time the TreeItem changes, check, if the new item is a
// child of the root and set the pseudoclass accordingly
row.treeItemProperty().addListener((o, oldValue, newValue) -> {
boolean tn = false;
if (newValue != null) {
tn = newValue.getParent() == root;
}
row.pseudoClassStateChanged(topNode, tn);
});
return row;
});
// fill tree structure
TreeItem<Item> c1 = new TreeItem<>(new Item("category 1", null));
c1.getChildren().addAll(
new TreeItem<>(new Item("sub1.1", "foo")),
new TreeItem<>(new Item("sub1.2", "bar")));
TreeItem<Item> c2 = new TreeItem<>(new Item("category 2", null));
c2.getChildren().addAll(
new TreeItem<>(new Item("sub2.1", "answer")),
new TreeItem<>(new Item("sub2.2", "42")));
root.getChildren().addAll(c1, c2);
Scene scene = new Scene(ttv);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.tree-table-row-cell:top-node {
-fx-background: orange;
}
Moving the images a bit to the left would also be nice.
通常您从 TreeTableColumn.cellFactory
返回的自定义 TreeTableCell
执行此操作。根据您要实现的行为,设置 fitWidth
/fitHeight
可能就足够了,但在其他情况下,可能需要根据单元格大小动态修改这些值。
我有一个餐厅菜单,其中包含在 javaFX 中实现为 treeTableView 的菜肴和类别。
我想让类别行看起来与 CSS 不同,但我找不到过滤它们并应用 class 的方法。将图像向左移动一点也很好。我也没有运气使用 rowFactory。我看过
这就是我填写 table 的方式。我省略了列和细胞工厂。
private void fillDishes(List<Dish> dishes){
root.getChildren().clear();
Map<String,TreeItem<Dish>> categoryMap = new HashMap<>();
for (Category c: allCats) {
TreeItem<Dish> newCat = new TreeItem<>(new Dish(c.getName(),null,null,null));
//newCat.getGraphic().getStyleClass().add("category");
categoryMap.put(c.getName(),newCat);
root.getChildren().add(newCat);
}
for (Dish d: dishes) {
categoryMap.get(d.getCategory()).getChildren().add(new TreeItem<>(d));
}
}
TreeTableView
使用 rowFactory
创建 TreeTableRow
。稍后它会将 TreeItem
分配给 TreeTableRow
。对于同一行,不同的 TreeItem
可能会再次发生这种情况。为此,您需要处理更改,这些更改可以通过将 ChangeHandler
添加到 TreeTableRow.treeItem
属性 来完成。如果将新的 TreeItem
分配给该行,您可以通过检查该行项的(不可见)根项的子项来检查顶级节点。
我更喜欢不需要搜索子列表的方法。可以将项目的父项与根进行比较。
public static class Item {
private final String value1;
private final String value2;
public Item(String value1, String value2) {
this.value1 = value1;
this.value2 = value2;
}
public String getValue1() {
return value1;
}
public String getValue2() {
return value2;
}
}
@Override
public void start(Stage primaryStage) {
final TreeItem<Item> root = new TreeItem<>(null);
TreeTableView<Item> ttv = new TreeTableView<>(root);
ttv.setShowRoot(false);
TreeTableColumn<Item, String> column1 = new TreeTableColumn<>();
column1.setCellValueFactory(new TreeItemPropertyValueFactory<>("value1"));
TreeTableColumn<Item, String> column2 = new TreeTableColumn<>();
column2.setCellValueFactory(new TreeItemPropertyValueFactory<>("value2"));
ttv.getColumns().addAll(column1, column2);
final PseudoClass topNode = PseudoClass.getPseudoClass("top-node");
ttv.setRowFactory(t -> {
final TreeTableRow<Item> row = new TreeTableRow<>();
// every time the TreeItem changes, check, if the new item is a
// child of the root and set the pseudoclass accordingly
row.treeItemProperty().addListener((o, oldValue, newValue) -> {
boolean tn = false;
if (newValue != null) {
tn = newValue.getParent() == root;
}
row.pseudoClassStateChanged(topNode, tn);
});
return row;
});
// fill tree structure
TreeItem<Item> c1 = new TreeItem<>(new Item("category 1", null));
c1.getChildren().addAll(
new TreeItem<>(new Item("sub1.1", "foo")),
new TreeItem<>(new Item("sub1.2", "bar")));
TreeItem<Item> c2 = new TreeItem<>(new Item("category 2", null));
c2.getChildren().addAll(
new TreeItem<>(new Item("sub2.1", "answer")),
new TreeItem<>(new Item("sub2.2", "42")));
root.getChildren().addAll(c1, c2);
Scene scene = new Scene(ttv);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.tree-table-row-cell:top-node {
-fx-background: orange;
}
Moving the images a bit to the left would also be nice.
通常您从 TreeTableColumn.cellFactory
返回的自定义 TreeTableCell
执行此操作。根据您要实现的行为,设置 fitWidth
/fitHeight
可能就足够了,但在其他情况下,可能需要根据单元格大小动态修改这些值。