When i double-click the right border of a column's header cell - it automatically adjust the width of a column. How can i do same programmatically?
Asked
Active
Viewed 5,028 times
0
-
1Possible duplicate of [JavaFX TableColumn resize to fit cell content](http://stackoverflow.com/questions/23284437/javafx-tablecolumn-resize-to-fit-cell-content) – DVarga Jun 29 '16 at 05:46
-
i don't see there answer for my question, sry – Alexander Cyberman Jun 29 '16 at 08:25
4 Answers
4
Finally I found the solution:
TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (TableColumnHeader columnHeader : rootHeader.getColumnHeaders()) {
try {
TableColumn<?, ?> column = (TableColumn<?, ?>) columnHeader.getTableColumn();
if (column != null) {
Method method = skin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
method.setAccessible(true);
method.invoke(skin, column, 30);
}
} catch (Throwable e) {
e = e.getCause();
e.printStackTrace(System.err);
}
}
Javafx still crude. Many simple things need to do through deep ass...

Alexander Cyberman
- 2,114
- 3
- 20
- 21
4
(not only internal) API changed from fx8 to fx9:
- TableViewSkin (along with all skin implementations) moved into public scope: now it would be okay to subclass and implement whatever additional functionality is needed
tableViewSkin.getTableHeaderRow()
andtableHeaderRow.getRootHeader()
changed from protected to package-private scope, the only way to legally access any is via lookup- implementation of resizeToFitContent moved from skin to a package-private utility class TableSkinUtils, no way to access at all
- TableColumnHeader got a private
doColumnAutoSize(TableColumnBase, int)
that calls the utility method, provided the column's prefWidth has its default value 80. On the bright side: due to that suboptimal api we can grab an arbitrary header and auto-size any column
In code (note: this handles all visible leaf columns as returned by the TableView, nested or not - if you want to include hidden columns, you'll need to collect them as well)
/**
* Resizes all visible columns to fit its content. Note that this does nothing if a column's
* prefWidth is != 80.
*
* @param table
*/
public static void doAutoSize(TableView<?> table) {
// good enough to find an arbitrary column header
// due to sub-optimal api
TableColumnHeader header = (TableColumnHeader) table.lookup(".column-header");
if (header != null) {
table.getVisibleLeafColumns().stream().forEach(column -> doColumnAutoSize(header, column));
}
}
public static void doColumnAutoSize(TableColumnHeader columnHeader, TableColumn column) {
// use your preferred reflection utility method
FXUtils.invokeGetMethodValue(TableColumnHeader.class, columnHeader, "doColumnAutoSize",
new Class[] {TableColumnBase.class, Integer.TYPE},
new Object[] {column, -1});
}

kleopatra
- 51,061
- 28
- 99
- 211
1
Using the above excellent answer posted by Александр Киберман, I created a class to handle this and the issue of getSkin() == null:
import com.sun.javafx.scene.control.skin.NestedTableColumnHeader;
import com.sun.javafx.scene.control.skin.TableColumnHeader;
import com.sun.javafx.scene.control.skin.TableHeaderRow;
import com.sun.javafx.scene.control.skin.TableViewSkin;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.lang.reflect.Method;
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
public class TableViewPlus extends TableView
{
private boolean flSkinPropertyListenerAdded = false;
// ---------------------------------------------------------------------------------------------------------------------
public TableViewPlus()
{
super();
this.setEditable(false);
}
// ---------------------------------------------------------------------------------------------------------------------
public TableViewPlus(final ObservableList toItems)
{
super(toItems);
this.setEditable(false);
}
// ---------------------------------------------------------------------------------------------------------------------
public void resizeColumnsToFit()
{
if (this.getSkin() != null)
{
this.resizeColumnsPlatformCheck();
}
else if (!this.flSkinPropertyListenerAdded)
{
this.flSkinPropertyListenerAdded = true;
// From https://stackoverflow.com/questions/38718926/how-to-get-tableheaderrow-from-tableview-nowadays-in-javafx
// Add listener to detect when the skin has been initialized and therefore this.getSkin() != null.
this.skinProperty().addListener((a, b, newSkin) -> this.resizeColumnsPlatformCheck());
}
}
// ---------------------------------------------------------------------------------------------------------------------
private void resizeColumnsPlatformCheck()
{
if (Platform.isFxApplicationThread())
{
this.resizeAllColumnsUsingReflection();
}
else
{
Platform.runLater(this::resizeAllColumnsUsingReflection);
}
}
// ---------------------------------------------------------------------------------------------------------------------
// From https://stackoverflow.com/questions/38090353/javafx-how-automatically-width-of-tableview-column-depending-on-the-content
// Geesh. . . .
private void resizeAllColumnsUsingReflection()
{
final TableViewSkin<?> loSkin = (TableViewSkin<?>) this.getSkin();
// The skin is not applied till after being rendered. Which is happening with the About dialog.
if (loSkin == null)
{
System.err.println("Skin is null");
return;
}
final TableHeaderRow loHeaderRow = loSkin.getTableHeaderRow();
final NestedTableColumnHeader loRootHeader = loHeaderRow.getRootHeader();
for (final TableColumnHeader loColumnHeader : loRootHeader.getColumnHeaders())
{
try
{
final TableColumn<?, ?> loColumn = (TableColumn<?, ?>) loColumnHeader.getTableColumn();
if (loColumn != null)
{
final Method loMethod = loSkin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
loMethod.setAccessible(true);
loMethod.invoke(loSkin, loColumn, 30);
}
}
catch (final Throwable loErr)
{
loErr.printStackTrace(System.err);
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
}
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------

Eddie Fann
- 81
- 3
0
table.skinProperty().addListener((a, b, newSkin) -> {
TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (TableColumnHeader columnHeader : rootHeader.getColumnHeaders()) {
try {
TableColumn<?, ?> column = (TableColumn<?, ?>) columnHeader.getTableColumn();
if (column != null) {
Method method = skin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
method.setAccessible(true);
method.invoke(skin, column, 30);
}
} catch (Throwable e) {
e = e.getCause();
e.printStackTrace(System.err);
}
}
});
In order to prevent getSkin() == null;

Guangheng Xu
- 149
- 1
- 10