【问题标题】:JavaFX TableView with two fixed-columns and last one taking available spaceJavaFX TableView 有两个固定列,最后一个占用可用空间
【发布时间】:2016-06-01 01:28:13
【问题描述】:

我正在尝试制作一个简单的 3 列 TableView:

  • 一个包含固定大小图标的图标列。此列不能调整大小,并且必须具有固定大小。
  • 一个具有预定义首选大小的文本列,可以根据需要调整大小。
  • 最后一列占用所有可用空间。

不幸的是,这个简单的用例对于 Java FX 8 来说似乎真的很复杂。我尝试了以下方法,根据我对文档的理解,它应该可以工作:

TableColumn<DebuggerItem, ImageView> iconColumn = new TableColumn<>("ICON");
TableColumn<DebuggerItem, String> typeColumn = new TableColumn<>("TEXT");
TableColumn<DebuggerItem, String> textColumn = new TableColumn<>("DATA");
setColumnResizePolicy(CONSTRAINED_RESIZE_POLICY);
// Fixed size column
iconColumn.setPrefWidth(40);
iconColumn.setMinWidth(40);
iconColumn.setMaxWidth(40);
iconColumn.setResizable(false);
// Predefined preferred size of 100px
typeColumn.setPrefWidth(100);
getColumns().addAll(iconColumn, typeColumn, textColumn);

这会产生以下 TableView:

我们可以看到,如果第一列的大小正确,那么第二列和第三列的大小相同,这不是我所期望的。第二列应为 100px 宽,最后一列占据剩余空间。

我错过了什么?

【问题讨论】:

标签: java javafx tableview javafx-8


【解决方案1】:

您可以在将所有列添加到表后调用以下代码。

当调整大小的代码没有明确的列列表时,这很好。

  public static void makeLastColumnGrow(TableView<?> items) {
    var last = items.getColumns().get(items.getColumns().size() - 1);

    var aBinding = Bindings.createDoubleBinding(() ->{
        double width = items.getWidth();
        for (int i = 0; i < items.getColumns().size() - 1  ; i++) {

            width = width - items.getColumns().get(i).getWidth();
        }
         
        return width - 2; // minus -2 to account for border i think
    }, items.widthProperty());

    last.prefWidthProperty().bind(aBinding);
}

【讨论】:

    【解决方案2】:

    我创建了一个更通用的解决方案,它可以完美地计算 TableViews 的最后一列的宽度:

    • 有任意数量的列
    • 可能在运行时隐藏或显示列
    • 可能有自定义插图
    • 可能有滚动条,可能在运行时显示和隐藏。

    用法: bindLastColumnWidth(tableView);

    来源:

    public static <T> void bindLastColumnWidth (TableView<T> tableView) {
        List<TableColumn<T,?>> columns = tableView.getColumns();
        List<TableColumn<T,?>> columnsWithoutLast = columns.subList(0, columns.size() - 1);
        TableColumn lastColumn = columns.get(columns.size() - 1);
    
        NumberExpression expression = tableView.widthProperty();
        Insets insets = tableView.getInsets();
        expression = expression.subtract(insets.getLeft() + insets.getRight());
    
        for (TableColumn column : columnsWithoutLast) {
            NumberExpression columnWidth = Bindings.when(column.visibleProperty())
                .then(column.widthProperty())
                .otherwise(0);
            expression = expression.subtract(columnWidth);
        }
    
        ScrollBar verticalScrollBar = getScrollBar(tableView, Orientation.VERTICAL);
        if (verticalScrollBar != null) {
            NumberExpression scrollBarWidth = Bindings.when(verticalScrollBar.visibleProperty())
                .then(verticalScrollBar.widthProperty())
                .otherwise(0);
            expression = expression.subtract(scrollBarWidth);
        }
    
        expression = Bindings.max(lastColumn.getPrefWidth(), expression);
    
        lastColumn.prefWidthProperty().bind(expression);
    }
    
    private static ScrollBar getScrollBar (Node control, Orientation orientation) {
        for (Node node : control.lookupAll(".scroll-bar")) {
            if (node instanceof ScrollBar) {
                ScrollBar scrollBar = (ScrollBar)node;
                if (scrollBar.getOrientation().equals(orientation)) {
                    return scrollBar;
                }
            }
        }
        return null;
    }
    

    【讨论】:

      【解决方案3】:

      根据@kleopatra 链接,解决方案是使用属性来计算最后一列的宽度,而不是使用CONSTRAINED_RESIZE_POLICY

      LastColumnWidth = TableViewWidth - SUM(Other Columns Widths)
      

      根据我的示例,给出以下 Java 代码:

      TableColumn<DebuggerItem, ImageView> iconColumn = new TableColumn<>("ICON");
      TableColumn<DebuggerItem, String> typeColumn = new TableColumn<>("TEXT");
      TableColumn<DebuggerItem, String> textColumn = new TableColumn<>("DATA");
      // Fixed size column
      iconColumn.setPrefWidth(40);
      iconColumn.setMinWidth(40);
      iconColumn.setMaxWidth(40);
      iconColumn.setResizable(false);
      // Predefined preferred size of 100px
      typeColumn.setPrefWidth(100);
      // Automatic width for last column
      textColumn.prefWidthProperty().bind(
          widthProperty().subtract(
             iconColumn.widthProperty()).subtract(
             typeColumn.widthProperty()).subtract(2)
      );
      getColumns().addAll(iconColumn, typeColumn, textColumn);
      

      请注意,我们需要减去 2 个像素才能得到确切的宽度,不清楚原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-26
        • 1970-01-01
        • 2015-07-04
        • 1970-01-01
        • 1970-01-01
        • 2021-11-04
        • 2012-08-10
        相关资源
        最近更新 更多