JavaFX TreeView TreeColumn自动调整大小以适合内容 [英] JavaFX TreeView TreeColumn auto-size to fit content

查看:4800
本文介绍了JavaFX TreeView TreeColumn自动调整大小以适合内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图找出如何自动调整TreeView列以适应他们的内容一段时间。

I have been trying to figure out how to auto-size TreeView columns to fit their content for a while now. This has been asked before, but the response was minimal and not acceptable.

[ http://stackoverflow.com/questions/14650787/javafx-column-in-tableview-auto-fit-size] [1] a>

[http://stackoverflow.com/questions/14650787/javafx-column-in-tableview-auto-fit-size][1]

奇怪的是,我在寻找的行为正是当你在TableView中双击列调整大小行时会发生什么。但是,我通过JavaFX源代码找不到这是怎么发生的。

Curiously, the behavior I'm looking for is exactly what happens when you double-click a column resize line in TableView. However, I have been unable to figure out how this occurs when looking through the JavaFX source code.

有人知道如何/在列上的双击行为调整大小line在JavaFX中处理TableView / TableColumn / TableColumnHeader?

Does anyone know how/where the double-click behavior on a column resize line is handled in JavaFX TableView/TableColumn/TableColumnHeader?

如果可能,我只想让列自动做,首先渲染当你双击调整大小线。

If possible, I would simply like the columns to automatically do at first render what happens when you double-click the resize line. How this isn't already one of the available pre-created column size constraint policies is beyond me.

推荐答案

这里是FINAL解决方案我想出了JavaFX 2.2,现在也考虑了列标题的宽度:

Here is the FINAL solution I came up with for JavaFX 2.2 which now also accounts for the width of the column header:

/**
 * Auto-sizes table view columns to fit its contents.
 * 
 * @note This is not a column resize policy and does not prevent manual
 *       resizing after this method has been called.
 * @param tableView
 *            The table view in which to resize all columns.
 */
public static void autoSizeTableViewColumns(final TableView<?> tableView)
{
    autoSizeTableViewColumns(tableView, -1, -1);
}

/**
 * Auto-sizes table view columns to fit its contents.
 * 
 * @note This is not a column resize policy and does not prevent manual
 *       resizing after this method has been called.
 *       
 * @param tableView
 *            The table view in which to resize all columns.
 * @param minWidth
 *            Minimum desired width of text for all columns.
 * @param maxWidth
 *            Maximum desired width of text for all columns.
 */
public static void autoSizeTableViewColumns(final TableView<?> tableView, int minWidth, int maxWidth)
{
    TableViewSkin<?> skin = (TableViewSkin<?>) tableView.getSkin();

    if (skin == null)
    {
        AppLogger.getLogger().warning(tableView + " skin is null.");
        return;
    }

    TableHeaderRow headerRow = skin.getTableHeaderRow();
    NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
    for (Node node : rootHeader.getChildren())
    {
        if (node instanceof TableColumnHeader)
        {
            TableColumnHeader columnHeader = (TableColumnHeader) node;
            try
            {
                autoSizeTableViewColumn(columnHeader, minWidth, maxWidth, -1);
            }
            catch (Throwable e)
            {
                e = e.getCause();
                AppLogger.getLogger().log(Level.WARNING, "Unable to automatically resize tableView column.", e);
            }
        }
    }
}

/**
 * Auto-sizes table view columns to fit its contents.
 * 
 * @note This is not a column resize policy and does not prevent manual
 *       resizing after this method has been called.
 *       
 * @param col
 *            The column to resize.
 * @param minWidth
 *            Minimum desired width of text for this column. Use -1 for no minimum
 *            width.
 * @param maxWidth
 *            Maximum desired width of text for this column. Use -1 for no maximum
 *            width.
 * @param maxRows
 *            Maximum number of rows to examine for auto-resizing. Use -1
 *            for all rows.
 */
public static void autoSizeTableViewColumn(TableColumn<?,?> column, int minWidth, int maxWidth, int maxRows)
{
    TableView<?> tableView = column.getTableView();
    TableViewSkin<?> skin = (TableViewSkin<?>) tableView.getSkin();

    if (skin == null)
    {
        AppLogger.getLogger().warning(tableView + " skin is null.");
        return;
    }

    TableHeaderRow headerRow = skin.getTableHeaderRow();
    NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
    for (Node node : rootHeader.getChildren())
    {
        if (node instanceof TableColumnHeader)
        {
            TableColumnHeader columnHeader = (TableColumnHeader) node;
            if(columnHeader.getTableColumn().equals(column))
            {
                autoSizeTableViewColumn(columnHeader, minWidth, maxWidth, maxRows);
            }
        }
    }
}

/**
 * Auto-sizes a table view column to fit its contents.
 * 
 * @note This is not a column resize policy and does not prevent manual
 *       resizing after this method has been called.
 * 
 * @param col
 *            The column to resize.
 * @param minWidth
 *            Minimum desired width of text for this column. Use -1 for no minimum
 *            width.
 * @param maxWidth
 *            Maximum desired width of text for this column. Use -1 for no maximum
 *            width.
 * @param maxRows
 *            Maximum number of rows to examine for auto-resizing. Use -1
 *            for all rows.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void autoSizeTableViewColumn(TableColumnHeader header, int minWidth, int maxWidth, int maxRows)
{
    TableColumn<?, ?> col = header.getTableColumn();
    if(col != null)
    {
        List<?> items = col.getTableView().getItems();
        if (items == null || items.isEmpty())
            return;

        Callback cellFactory = col.getCellFactory();
        if (cellFactory == null)
            return;

        TableCell cell = (TableCell) cellFactory.call(col);
        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 TableColumn
        cell.getProperties().put("deferToParentPrefWidth", 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.getInsets().getLeft() + r.getInsets().getRight();
        }

        int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows);

        double desiredWidth = 0;

        // Check header
        Label headerLabel = (Label) header.lookup(".label");
        String headerText = headerLabel.getText();
        if (!headerLabel.getContentDisplay().equals(ContentDisplay.GRAPHIC_ONLY) && headerText != null)
        {
            Text text = new Text(headerLabel.getText());
            text.setFont(headerLabel.getFont());
            desiredWidth += text.getLayoutBounds().getWidth() + headerLabel.getLabelPadding().getLeft() + headerLabel.getLabelPadding().getRight();
        }

        Node headerGraphic = headerLabel.getGraphic();
        if((headerLabel.getContentDisplay().equals(ContentDisplay.LEFT) || headerLabel.getContentDisplay().equals(ContentDisplay.RIGHT)) && headerGraphic != null)
        {
            desiredWidth += headerGraphic.getLayoutBounds().getWidth();
        }

        // Handle minimum width calculations
        // Use a "w" because it is typically the widest character
        Text minText = new Text(StringUtils.repeat("W", Math.min(0, minWidth)));
        minText.setFont(headerLabel.getFont());

        // Check rows
        double minPxWidth = 0;
        for (int row = 0; row < rows; row++)
        {
            cell.updateTableColumn(col);
            cell.updateTableView(col.getTableView());
            cell.updateIndex(row);

            // Handle minimum width calculations
            // Just do this once
            if(row == 0)
            {
                String oldText = cell.getText();
                // Use a "w" because it is typically the widest character
                cell.setText(StringUtils.repeat("W", Math.max(0, minWidth)));

                header.getChildren().add(cell);
                cell.impl_processCSS(false);
                minPxWidth = cell.prefWidth(-1);
                header.getChildren().remove(cell);

                cell.setText(oldText);
            }

            if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null)
            {
                header.getChildren().add(cell);
                cell.impl_processCSS(false);
                desiredWidth = Math.max(desiredWidth, cell.prefWidth(-1));
                desiredWidth = Math.max(desiredWidth, minPxWidth);
                header.getChildren().remove(cell);
            }
        }

        desiredWidth = desiredWidth + padding;

        if(maxWidth > 0)
        {
            desiredWidth = Math.min(maxWidth, desiredWidth);
        }

        col.impl_setWidth(desiredWidth);
    }
}

请记住,这是黑客这可以随时更改与JavaFX更新和打破该方法。我相信这已经改变了JavaFX 8.这也可以打破取决于你的应用程序如何签署部署。

Keep in mind that this is "hacking" protected methods which could change at any time with a JavaFX update and break the method. I believe this already changes in JavaFX 8. This could also break depending upon how your application is signed an deployed.

这不漂亮,但JavaFX已隐藏此功能所以除非你想重新实现整个事情,这是我发现的最好的方法。

It isn't pretty, but JavaFX has hidden this functionality so unless you want to re-implement the entire thing, this is the best approach I've found.

这篇关于JavaFX TreeView TreeColumn自动调整大小以适合内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆