JDK 8 TreeView 披露三角形垂直对齐不正确

问题描述 投票:0回答:4

我制作了一个高度为 40 px 的自定义树单元。

这里有一个问题披露三角形没有垂直居中对齐。

enter image description here

这里是树单元的代码:

public static class TestObjectCell extends AnchorPane implements ISMPBVisualComponentWithData<TestObject>{

        public Label label;

        public TestObjectCell(){
            label=new Label("label");
            AnchorPane.setTopAnchor(label, 10.0);
            this.getChildren().setAll(label);
            this.setMinHeight(40);
            this.setPrefHeight(40);
            this.setMaxHeight(40);
        }


        @Override
        public void setComponentData(TestObject object) {
            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }



    }

正如您在顶部对齐的图片披露三角形中看到的那样,如何对齐单元格的垂直中心?

treeview javafx-2 javafx java-8
4个回答
1
投票

我也有同样的问题。我使用单元工厂来翻译 TreeCell 的公开节点:

myTree.setCellFactory(treeView -> {

        final TreeCell<Label> cell = new TreeCell<Label>() {
            @Override public void updateItem(Label item, boolean empty) {
                super.updateItem(item, empty);

                if (empty) {
                    setGraphic(null);
                } else {
                    final Node graphic = (getTreeItem() == null) ? null : getTreeItem().getGraphic();
                    setGraphic((graphic != null) ? graphic : (item != null) ? item.getGraphic() : null);  
                }
                setText((empty || item == null) ? null : item.getText()); 
            }
        };          

        cell.disclosureNodeProperty().addListener((obs, oldNode, newNode) -> {
            final StackPane pane = (StackPane) newNode;
            newNode.translateYProperty().bind(cell.heightProperty().multiply(0.5).subtract(pane.heightProperty()));
        }); 
        return cell;
});

当然必须有更好的方法来做到这一点,但至少这对我有用。


0
投票

您是否尝试过在 TreeCell 中设置 alignment 属性


0
投票

我发现更改公开节点对齐方式的唯一方法是使用

-fx-padding
样式手动覆盖垂直填充:

.tree-disclosure-node {
   -fx-padding: 0.85em 0.229em 0.333333em 0.229em;
}

这将允许您根据需要使箭头居中,但如果行高发生变化,您将需要修改此值。


0
投票

我发现了一个非常简洁的解决方案,通过提供一个自定义单元工厂,将树公开节点的高度绑定到单元高度:

public class ArrowCenteringFactory<T> implements Callback<TreeView<T>, TreeCell<T>>
{
  private Callback<TreeView<T>, TreeCell<T>> original = CheckBoxTreeCell.<T> forTreeView();

  @Override
  public TreeCell<T> call(TreeView<T> tree)
  {
    TreeCell<T> cell = original.call(tree);
    bindDisclosureNodeHeightToCellHeight(cell);
    return cell;
  }

  /**
   * The disclosure node is monitored being able to bind its height to the cell height in the same way {@link TreeCellSkin#layoutChildren} called by {@link Control#layoutChildren}.
   * The default tree-disclosure-node is created in {@link TreeViewSkin#createCell}.
   */
  private void bindDisclosureNodeHeightToCellHeight(TreeCell<T> cell)
  {
    cell.disclosureNodeProperty().addListener((ChangeListener<Node>) (observable, oldValue, newValue) ->
    {
      if (oldValue instanceof Region)
      {
        Region old = (Region) oldValue;
        old.prefHeightProperty().unbind();
      }
      if (newValue instanceof Region)
      {
        Region node = (Region) newValue;
        node.prefHeightProperty()
            .bind(Bindings.createDoubleBinding(() -> cell.snapSizeY(cell.getHeight()) - cell.snappedTopInset() - cell.snappedBottomInset(),
                                               cell.heightProperty(), cell.insetsProperty()));
      }
    });
  }
}

因为默认的树公开节点是

StackPane
,所以它的
.arrow
子节点将自动位于
StackPane
的中心。

您需要通过调用来设置工厂

tree.setCellFactory(new ArrowCenteringFactory<>());
© www.soinside.com 2019 - 2024. All rights reserved.