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

jck*_*111 10 javafx tableview

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

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

小智 8

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

/*
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

它在宣布

com.sun.javafx.scene.control.skin.TableViewSkinBase
Run Code Online (Sandbox Code Playgroud)

方法签名

protected abstract void resizeColumnToFitContent(TC tc, int maxRows)
Run Code Online (Sandbox Code Playgroud)

由于它受到保护,你不能从例如tableView.getSkin()调用它,但是你总是可以扩展TableViewSkin只覆盖resizeColumnToFitContent方法并使其公开.

  • 刚刚输入https://javafx-jira.kenai.com/browse/RT-39533就可以以较少的hacky方式进行操作. (2认同)
  • 新网站上的错误:https://bugs.openjdk.java.net/browse/JDK-8092235 (2认同)

yel*_*ver 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();
                    }
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在JDK 9上,我得到了NoSuchMethodException :( (2认同)

Tam*_*ang 0

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

您还可以尝试在两种策略之间进行切换TableView.CONSTRAINED_RESIZE_POLICYTableView.UNCONSTRAINED_RESIZE_POLICY以防TableView.UNCONSTRAINED_RESIZE_POLICY单独使用不能满足您的需求。

这是一个有用的链接。