JavaFX TableColumn调整大小以适合单元格内容

时间:2014-04-25 04:52:45

标签: javafx tableview

我正在寻找一种方法来调整TableView中TableColumn的大小,以便所有内容在每个单元格中都可见(即没有截断)。

我注意到双击列分隔符会自动使列适合其单元格的内容。有没有办法以编程方式触发它?

4 个答案:

答案 0 :(得分:8)

通过javafx源代码挖掘,我发现单击TableView列分隔符时调用的实际方法是

/*
 * FIXME: Naive implementation ahead
 * Attempts to resize column based on the pref width of all items contained
 * in this column. This can be potentially very expensive if the number of
 * rows is large.
 */
@Override protected void resizeColumnToFitContent(TableColumn<T, ?> tc, int maxRows) {
    if (!tc.isResizable()) return;

// final TableColumn<T, ?> col = tc;
    List<?> items = itemsProperty().get();
    if (items == null || items.isEmpty()) return;

    Callback/*<TableColumn<T, ?>, TableCell<T,?>>*/ cellFactory = tc.getCellFactory();
    if (cellFactory == null) return;

    TableCell<T,?> cell = (TableCell<T, ?>) cellFactory.call(tc);
    if (cell == null) return;

    // set this property to tell the TableCell we want to know its actual
    // preferred width, not the width of the associated TableColumnBase
    cell.getProperties().put(TableCellSkin.DEFER_TO_PARENT_PREF_WIDTH, Boolean.TRUE);

    // determine cell padding
    double padding = 10;
    Node n = cell.getSkin() == null ? null : cell.getSkin().getNode();
    if (n instanceof Region) {
        Region r = (Region) n;
        padding = r.snappedLeftInset() + r.snappedRightInset();
    } 

    int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows);
    double maxWidth = 0;
    for (int row = 0; row < rows; row++) {
        cell.updateTableColumn(tc);
        cell.updateTableView(tableView);
        cell.updateIndex(row);

        if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) {
            getChildren().add(cell);
            cell.applyCss();
            maxWidth = Math.max(maxWidth, cell.prefWidth(-1));
            getChildren().remove(cell);
        }
    }

    // dispose of the cell to prevent it retaining listeners (see RT-31015)
    cell.updateIndex(-1);

    // RT-36855 - take into account the column header text / graphic widths.
    // Magic 10 is to allow for sort arrow to appear without text truncation.
    TableColumnHeader header = getTableHeaderRow().getColumnHeaderFor(tc);
    double headerTextWidth = Utils.computeTextWidth(header.label.getFont(), tc.getText(), -1);
    Node graphic = header.label.getGraphic();
    double headerGraphicWidth = graphic == null ? 0 : graphic.prefWidth(-1) + header.label.getGraphicTextGap();
    double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset();
    maxWidth = Math.max(maxWidth, headerWidth);

    // RT-23486
    maxWidth += padding;
    if(tableView.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY) {
        maxWidth = Math.max(maxWidth, tc.getWidth());
    }

    tc.impl_setWidth(maxWidth);
}

中声明
com.sun.javafx.scene.control.skin.TableViewSkinBase

方法签名

protected abstract void resizeColumnToFitContent(TC tc, int maxRows)

由于受到保护,您无法通过例如tableView.getSkin(),但您始终可以扩展TableViewSkin,只覆盖resizeColumnToFitContent方法并将其公开。

答案 1 :(得分:6)

作为@Tomasz的建议,我通过反思来解决:

import com.sun.javafx.scene.control.skin.TableViewSkin;
import javafx.scene.control.Skin;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class GUIUtils {
    private static Method columnToFitMethod;

    static {
        try {
            columnToFitMethod = TableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
            columnToFitMethod.setAccessible(true);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public static void autoFitTable(TableView tableView) {
        tableView.getItems().addListener(new ListChangeListener<Object>() {
            @Override
            public void onChanged(Change<?> c) {
                for (Object column : tableView.getColumns()) {
                    try {
                        columnToFitMethod.invoke(tableView.getSkin(), column, -1);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

答案 2 :(得分:2)

如果从不设置prefWidth(或将其设置为80.0F,请参见TableColumnHeader enter link description here),则当前版本的JavaFX(例如15-ea + 1)将调整表列的大小。

答案 3 :(得分:0)

您可以使用tableView.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);

您还可以尝试在两个策略TableView.CONSTRAINED_RESIZE_POLICY之间切换 如果TableView.UNCONSTRAINED_RESIZE_POLICY不适合您的需要,请使用TableView.UNCONSTRAINED_RESIZE_POLICY。

Here's一个有用的链接。