Подтвердить что ты не робот

Столбец javafx в формате автозаполнения таблицы

afaik TableView в javafx имеет две политики изменения размера столбца: CONSTRAINED_RESIZE_POLICY и UNCONSTRAINED_RESIZE_POLICY, но я хочу, чтобы столбцы были изменены в соответствии с содержимым их ячеек Я думаю, что это простая проблема в другой платформе (например, datagridview в С#), но не может решить

4b9b3361

Ответ 1

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

Но я понимаю, что когда я нажимаю на разделитель на заголовке таблицы, он меняет размер на контент, как я хочу. Таким образом, я копаюсь в исходном коде JavaFX. Наконец, я нашел метод resizeColumnToFitContent в 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()

Ответ 2

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

Пример:

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

Ответ 3

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

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

Ответ 4

Или сделать это коротко:

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

Ответ 5

Я использовал другие решения по этому вопросу, и он работает очень хорошо. Однако недостатком этого является то, что ширина 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()));
    }

}

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

Ответ 6

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

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

fillingColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(usedWidth));

Ответ 7

Этот код автоматически анализирует все ширины столбцов в реляционных пропорциях до ширины таблицы,
в то время как он может фиксировать ширину первого столбца до заданного значения, когда ширина таблицы меньше, чем 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 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));
                        }

                    }
                });
            }
        }

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

Ответ 8

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

Ответ 9

myTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
for(TableColumn column: myTable.getColumns())
{           
    column.setMinWidth(200);                                        
}

Ответ 10

<TableView fx:id="datalist" layoutX="30.0" layoutY="65.0" prefHeight="400.0" AnchorPane.bottomAnchor="100.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="100.0">
        <columns>
            <TableColumn fx:id="number" minWidth="-1.0" prefWidth="-1.0" style="width: auto;" text="number" />
            <TableColumn fx:id="id" minWidth="-1.0" prefWidth="-1.0" text="id" />
            <TableColumn fx:id="name" minWidth="-1.0" prefWidth="-1.0" text="name" />
            <TableColumn fx:id="action" minWidth="-1.0" prefWidth="-1.0" text="todo" />
        </columns>
         **<columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>**
      </TableView>

Ответ 11

После долгих исследований. Лучшее решение..

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

"Пользовательский размер"

public void customResize(TableView<?> view) {

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

        if (tableWidth > width.get()) {
            view.getColumns().forEach(col -> {
                col.setPrefWidth(col.getWidth()+((tableWidth-width.get())/view.getColumns().size()));
            });
        }
    }