Search code examples
javafx-2javafx

Auto fit size column in table view


The TableView in JavaFX have 2 column resize policies:

CONSTRAINED_RESIZE_POLICY and UNCONSTRAINED_RESIZE_POLICY

But I want columns that are resized to fit the content of theirs cells.

How do I do this?


Solution

  • After 3 years I come back to this problem again, some suggestions are calculating the size of text of data in each cell (it's complicated depending on font size, font family, padding...)

    But I realize that when I click on the divider on table header, it's resized fit to content as I want. So I dig into JavaFX source code I finally found resizeColumnToFitContent method in TableViewSkin, but it is protected method, we can resolve by reflection:

    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();
                        }
                    }
                }
            });
        }
    }
    

    Note that we call "tableView.getItems()" so we have to call this function after setItems()