David Goodenough
David Goodenough

Reputation: 51

JavaFx-14 resizeColumnToFitContent method

JavaFx-14 put this method in the TableColumnHeader, rather than in the Skin. How does one find a TableColumnHeader from a TableColumn and a TableView?

Upvotes: 3

Views: 749

Answers (3)

Tharkius
Tharkius

Reputation: 3518

Don't know if you still need this, but if anyone else is interested, this is how I surpassed the problem in java, based on David Goodenough's scala code above.

The class for the TableSkin

import javafx.scene.control.TableColumnBase;
import javafx.scene.control.TableView;
import javafx.scene.control.skin.NestedTableColumnHeader;
import javafx.scene.control.skin.TableColumnHeader;
import javafx.scene.control.skin.TableHeaderRow;
import javafx.scene.control.skin.TableViewSkin;

import java.util.ArrayList;
import java.util.List;

public class CustomTableViewSkin extends TableViewSkin<Track> {
    private List<CustomTableColumnHeader> columnHeadersList = new ArrayList<>();

    private class CustomTableColumnHeader extends TableColumnHeader {
        /**
         * Creates a new TableColumnHeader instance to visually represent the given
         * {@link TableColumnBase} instance.
         *
         * @param tc The table column to be visually represented by this instance.
         */
        public CustomTableColumnHeader(TableColumnBase tc) {
            super(tc);
        }

        public void resizeColumnToFitContent() {
            super.resizeColumnToFitContent(-1);
        }
    }

    public CustomTableViewSkin(TableView<Track> tableView) {
        super(tableView);
    }

    @Override
    protected TableHeaderRow createTableHeaderRow() {
        return new TableHeaderRow(this) {
            @Override
            protected NestedTableColumnHeader createRootHeader() {
                return new NestedTableColumnHeader(null) {
                    @Override
                    protected TableColumnHeader createTableColumnHeader(TableColumnBase col) {
                        CustomTableColumnHeader columnHeader = new CustomTableColumnHeader(col);

                        if (columnHeadersList == null) {
                            columnHeadersList = new ArrayList<>();
                        }

                        columnHeadersList.add(columnHeader);

                        return columnHeader;
                    }
                };
            }
        };
    }

    public void resizeColumnToFit() {
        if (!columnHeadersList.isEmpty()) {
            for (CustomTableColumnHeader columnHeader : columnHeadersList) {
                columnHeader.resizeColumnToFitContent();
            }
        }
    }
}

And the class for the TableView

import javafx.scene.control.TableView;

public class CustomTableView extends TableView<Foo> {
    private final CustomTableViewSkin thisSkin;

    public CustomTableView() {
        super();

        setSkin(thisSkin = new CustomTableViewSkin(this));
    }

    public void resizeColumnsToFitContent() {
        if (thisSkin != null && getSkin() == thisSkin) {
            thisSkin.resizeColumnToFit();
        }
    }
}

Upvotes: 3

David Goodenough
David Goodenough

Reputation: 51

Well this code is Scala not Java, but for the record the code below works:-

    skin = new TableViewSkin(this) {
    override protected def createTableHeaderRow:TableHeaderRow = {
        new TableHeaderRow(this) {
            override protected def createRootHeader:NestedTableColumnHeader = {
                new NestedTableColumnHeader(null) {
                    override protected def createTableColumnHeader(col:TableColumnBase[_,_]) = {
                        val tableColumnHeader = new MyTableColumnHeader(col)
                        if(col == null || col.getColumns.isEmpty || col == getTableColumn) tableColumnHeader else new NestedTableColumnHeader(col)
                        }
                    }
                }
            }
        }
    } 
private class MyTableColumnHeader(tc:TableColumnBase[_,_]) extends TableColumnHeader(tc) {
    def resizeCol():Double = {
        resizeColumnToFitContent(-1)
        width.value
        }
    }

and then when I want to use it I use kleopatra's suggestion and:-

      val w = columns.map { col =>
            // To find the TableColumnHeader we can use column.getStyleableNode as suggested by kleopatra on StackOverflow:-
            // you get the header from coumn.getStyleableNode (took a moment, had to check if it's really implemented) – kleopatra Jul 1 at 20:46
            col.getStyleableNode() match {
                case mtch:MyTableColumnHeader => mtch.resizeCol
                case _ => col.width.get
                }
    }.sum

Upvotes: 1

Oboe
Oboe

Reputation: 2703

This is a hack'ish way of getting the TableColumnHeader:

public TableColumnHeader getTableColumnHeader(TableView<?> table, int index) {
    return (TableColumnHeader) table.queryAccessibleAttribute(AccessibleAttribute.COLUMN_AT_INDEX, index);
}

Or, as @kleopatra suggested, for a non-hack'ish approach you can do:

public TableColumnHeader getTableColumnHeader(TableView<?> table, int index) {
    return (TableColumnHeader) table.getColumns().get(index).getStyleableNode();
}

Make sure that the TableView is part of the scene graph.

However, the resizeColumnToFitContent method is protected and you won't be able to access it.

Upvotes: 0

Related Questions