JavaFX 2 Automatic Column Width
Asked Answered
T

7

50

I have a JavaFX 2 table that is displaying contact details for people, lets imagine there are three columns: first name, last name and email address. When my application starts it populates the table with several rows of data about the people already in the system.

The problem is that the column widths are all the same. Most of the time the first and last name is displayed in full but the email address is getting clipped. The user can double click the divider in the header to resize the column but that will become tedious quickly.

Once the table has been pre-populated I would like to programatically resize all the columns to display the data they contain but I can't figure out how to achieve this. I can see that I can call col.setPrefWidth(x) but that doesn't really help as I would have to guess the width.

Textual answered 14/4, 2012 at 10:20 Comment(0)
J
81

If your total number of columns are pre-known. You can distribute the column widths among the tableview's width:

nameCol.prefWidthProperty().bind(personTable.widthProperty().divide(4)); // w * 1/4
surnameCol.prefWidthProperty().bind(personTable.widthProperty().divide(2)); // w * 1/2
emailCol.prefWidthProperty().bind(personTable.widthProperty().divide(4)); // w * 1/4

In this code, the width proportions of columns are kept in sync when the tableview is resized, so you don't need to do it manually. Also the surnameCol takes the half space of the tableview's width.

Jacklin answered 14/4, 2012 at 10:47 Comment(0)
A
24

This works for me in JavaFX 8

table.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY );
col1.setMaxWidth( 1f * Integer.MAX_VALUE * 50 ); // 50% width
col2.setMaxWidth( 1f * Integer.MAX_VALUE * 30 ); // 30% width
col3.setMaxWidth( 1f * Integer.MAX_VALUE * 20 ); // 20% width

In the other examples you have the problem, the vertical scrollbar width is ignored.

Also answered 8/2, 2016 at 8:42 Comment(3)
Where do you see that you can pass percents to setMaxWidth ?Andro
Clever trick - big enough numbers so that proportional sizing down needs to be used to fit into the real size.Disject
Thanks, using your technique now. Still I faced problems with the vertical scrollbar width. When enough items are added that the vertical scrollbar appeared immediately, it caused a little offset between the vertical TableView lines of header and rows. I was able to fix this by refreshing the TableView: After myTableView.setItems(myObservableList); refresh the GUI (Graphical User Interface) by accessing the Application Thread with: line #1: Platform.runLater(new Runnable() { line #2: @Override public void run() { line #3: myTableView.refresh(); line#4: }});Feeley
H
4

As I use SceneBuider, I just define the MinWidth, and MaxWidth to some columns and to the main column I just define the PrefWidth to "USE_COMPUTED_SIZE"

Homeopathist answered 18/2, 2016 at 11:38 Comment(1)
The programmatic version of this is just col.setPrefWidth(Control.USE_COMPUTED_SIZE);Capitally
R
3

After 3 years, finally I found the solution, javafx column in tableview auto fit size

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();
                    }
                }
            }
        });
    }
}
Removal answered 31/7, 2016 at 17:7 Comment(3)
I can't find or import the class TableViewSkin. I'm using Java 8 and this class doesn't seem to exist.Tweeny
It does not exist any more, this solution can't be used with the newer JAVA versions. Please see: #50584412Pommel
@MindaugasBernatavičius it's long time I have not dev JavaFX, but when that method is removed, is it able to double click the column divider to auto fit, if it is, we can find the method triggerredRemoval
P
3

If you had 4 columns and only last column needed to expand to fill the rest of the table width and the other columns remained the size I set in Scene Builder.

double width = col1.widthProperty().get();
width += col2.widthProperty().get();
width += col3.widthProperty().get();

col4.prefWidthProperty().bind(table.widthProperty().subtract(width));

Or if you had 2 columns that needed to expand then.

double width = col1.widthProperty().get();
width += col3.widthProperty().get();

col2.prefWidthProperty().bind(table.widthProperty().subtract(width).divide(2));
col4.prefWidthProperty().bind(table.widthProperty().subtract(width).divide(2));
Potter answered 12/8, 2016 at 12:37 Comment(0)
P
2

Also, a very simple trick based on an AnchorPane will be a good solution.

We gonna wrap the TableView into a AnchorPane but also we gonna anchor the left and right side of the TableView like this:

AnchorPane wrapper = new AnchorPane();

AnchorPane.setRightAnchor(table, 10.0);
AnchorPane.setLeftAnchor(table, 10.0);
wrapper.getChildren().add(table);

This simple code will stretch the TableView in both directions (right and left) also, it will adjust whenever the scrollbar is added.

You can get an idea of how this works watching this animated gif.

enter image description here

Now you can resize the columns, adding these lines:

fnColumn.setMaxWidth( 1f * Integer.MAX_VALUE * 30 ); // 30% width
lnColumn.setMaxWidth( 1f * Integer.MAX_VALUE * 40 ); // 40% width
emColumn.setMaxWidth( 1f * Integer.MAX_VALUE * 30 ); // 30% width
Platino answered 13/7, 2018 at 9:23 Comment(0)
S
0

my idea.

table.getColumns().add(new TableColumn<>("Num") {
    {
        // 15%
        prefWidthProperty().bind(table.widthProperty().multiply(0.15));
    }
});
table.getColumns().add(new TableColumn<>("Filename") {{
    // 20%
    prefWidthProperty().bind(table.widthProperty().multiply(.2));
}});
table.getColumns().add(new TableColumn<>("Path") {{
    // 50%
    prefWidthProperty().bind(table.widthProperty().multiply(.5));
}});
table.getColumns().add(new TableColumn<>("Status") {
    {
        // 15%
        prefWidthProperty().bind(table.widthProperty().multiply(.15));
    }
});
Sax answered 12/8, 2020 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.