it-roy-ru.com

столбец javafx в таблице размеров

afaik TableView в javafx имеет две политики изменения размера столбцов: CONSTRAINED_RESIZE_POLICY и UNCONSTRAINED_RESIZE_POLICY, но я хочу, чтобы размер столбцов был изменен, чтобы соответствовать содержимому их ячеек. 

30
yelliver

Через 3 года я снова возвращаюсь к этой проблеме, некоторые предложения подсчитывают размер текста данных в каждой ячейке (это сложно в зависимости от размера шрифта, семейства шрифтов, отступов ...)

Но я понимаю, что когда я нажимаю на divider на заголовке таблицы, его размер изменяется в соответствии с тем, что я хочу. Итак, я копаюсь в исходном коде JavaFX, который, наконец, нашел resizeColumnToFitContent method в TableViewSkin , но это защищенный метод, который мы можем решить с помощью отражения:

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

Обратите внимание, что мы вызываем " tableView.getItems () ", поэтому мы должны вызывать эту функцию после setItems ()

22
yelliver

После тестирования предыдущих решений я, наконец, нашел то, что сработало для меня .... Итак, вот мое (вызов метода после вставки данных в таблицу):

public static void autoResizeColumns( TableView<?> table )
{
    //Set the right policy
    table.setColumnResizePolicy( TableView.UNCONSTRAINED_RESIZE_POLICY);
    table.getColumns().stream().forEach( (column) ->
    {
        //Minimal width = columnheader
        Text t = new Text( column.getText() );
        double max = t.getLayoutBounds().getWidth();
        for ( int i = 0; i < table.getItems().size(); i++ )
        {
            //cell must not be empty
            if ( column.getCellData( i ) != null )
            {
                t = new Text( column.getCellData( i ).toString() );
                double calcwidth = t.getLayoutBounds().getWidth();
                //remember new max-width
                if ( calcwidth > max )
                {
                    max = calcwidth;
                }
            }
        }
        //set the new max-widht with some extra space
        column.setPrefWidth( max + 10.0d );
    } );
}
5
HarleyDavidson

Я думаю, что просто переопределив функцию обратного вызова, которая возвращает true, решит вашу проблему, она отключит изменение размера столбцов, и все столбцы будут изменены в соответствии с содержимым их ячеек.

Пример:

TableView<String[]> table = new TableView<>();
table.setColumnResizePolicy(new Callback<TableView.ResizeFeatures, Boolean>() {
  @Override
  public Boolean call(ResizeFeatures p) {
     return true;
  }
});
5
vipul mittal

Я использовал другие решения по этому вопросу, и он работает довольно хорошо. Однако недостатком этого является то, что ширина TableView превышает требуемую ширину TableColumns вместе. Я создал хак для решения этой проблемы, и он работает нормально:

orderOverview.setColumnResizePolicy((param) -> true );
Platform.runLater(() -> FXUtils.customResize(orderOverview));

где FXUtils.customResize () создается следующим образом:

public static void customResize(TableView<?> view) {

    AtomicDouble width = new AtomicDouble();
    view.getColumns().forEach(col -> {
        width.addAndGet(col.getWidth());
    });
    double tableWidth = view.getWidth();

    if (tableWidth > width.get()) {
        TableColumn<?, ?> col = view.getColumns().get(view.getColumns().size()-1);
        col.setPrefWidth(col.getWidth()+(tableWidth-width.get()));
    }

}

Я надеюсь, что это может быть полезно и для других людей!

2
bashoogzaad

Или, чтобы сделать это коротким:

// automatically adjust width of columns depending on their content
configAttributeTreeTable.setColumnResizePolicy((param) -> true );
2
stefanil

Если вы хотите, чтобы только один столбец заполнил оставшуюся ширину таблицы, я нашел довольно прямолинейное решение, которое является коротким и не требует решения хакерского отражения, описанного выше:

DoubleBinding usedWidth = columnA.widthProperty().add(columnB.widthProperty()).add(columnC.widthProperty());

fillingColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(usedWidth));
2
Jeff S.
myTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
for(TableColumn column: myTable.getColumns())
{           
    column.setMinWidth(200);                                        
}
0
darkrepulser1957

Этот код автоматически изменяет ширину всех столбцов в относительных пропорциях к ширине таблицы, 
в то время как он может фиксировать ширину первого столбца к заданному значению, когда ширина таблицы меньше, чем x

        // To generalize the columns width proportions in relation to the table width,
        // you do not need to put pixel related values, you can use small float numbers if you wish,
        // because it's the relative proportion of each columns width what matters here:

        final float[] widths = { 1.2f, 2f, 0.8f };// define the relational width of each column 

        // whether the first column should be fixed
        final boolean fixFirstColumm = true; 

        // fix the first column width when table width is lower than:
        final float fixOnTableWidth = 360; //pixels 

        // calulates sum of widths
        float sum = 0;
        for (double i : widths) {
            sum += i;
        }

        // calculates the fraction of the first column proportion in relation to the sum of all column proportions
        float firstColumnProportion = widths[0] / sum;

        // calculate the fitting fix width for the first column, you can change it by your needs, but it jumps to this width
        final float firstColumnFixSize = fixOnTableWidth * firstColumnProportion;

        // set the width to the columns
        for (int i = 0; i < widths.length; i++) {
            table.getColumns().get(i).prefWidthProperty().bind(table.widthProperty().multiply((widths[i] / sum)));
            // ---------The exact width-------------^-------------^
    if (fixFirstColumm)
            if (i == 0) {
                table.widthProperty().addListener(new ChangeListener<Number>() {
                    @Override
                    public void changed(ObservableValue<? extends Number> arg0, Number oldTableWidth, Number newTableWidth) {

                        if (newTableWidth.intValue() <= fixOnTableWidth) {

                            // before you can set new value to column width property, need to unbind the autoresize binding
                            table.getColumns().get(0).prefWidthProperty().unbind();
                            table.getColumns().get(0).prefWidthProperty().setValue(firstColumnFixSize);

                        } else if (!table.getColumns().get(0).prefWidthProperty().isBound()) {

                            // than readd the autoresize binding if condition table.width > x
                            table.getColumns().get(0).prefWidthProperty()
                                    .bind(table.widthProperty().multiply(firstColumnProportion));
                        }

                    }
                });
            }
        }
</ PRE>

совет, чтобы поместить код в отдельный класс TableAutoresizeModel, там вы можете обрабатывать дальнейшие вычисления, например, для скрытия столбцов добавить слушателя ...

0
Henryk
public static void autoFillColumn(TableView<?> table, int col) {
    double width = 0;
    for (int i = 0; i < table.getColumns().size(); i++) {
        if (i != col) {
            width += table.getColumns().get(i).getWidth();
        }
    }
    table.getColumns().get(col).setPrefWidth(table.getWidth() - width);
}
0
Guillermo