remarquez que TableView dans javafx a deux stratégies de redimensionnement des colonnes: CONSTRAINED_RESIZE_POLICY et UNCONSTRAINED_RESIZE_POLICY, mais je veux que les colonnes soient redimensionnées pour s’ajuster au contenu de leurs cellules.
Après 3 ans, je reviens encore sur ce problème. Certaines suggestions calculent la taille du texte des données dans chaque cellule (c'est compliqué en fonction de la taille de la police, de la famille de police, du remplissage ...).
Mais je me rends compte que lorsque je clique sur l'en-tête divider on du tableau, il est redimensionné pour s'adapter au contenu que je veux. J'ai donc finalement trouvé la méthode resizeColumnToFitContent dans TableViewSkin , mais c'est protected méthode, nous pouvons résoudre par réflexion:
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();
}
}
}
});
}
}
Notez que nous appelons " tableView.getItems () ", nous devons donc appeler cette fonction après setItems ()
Après avoir testé les solutions précédentes, j’en ai finalement trouvé une qui fonctionnait pour moi… donc voici la mienne (appelez la méthode après avoir inséré les données dans le tableau):
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 );
} );
}
Je pense que le simple fait de redéfinir une fonction de rappel renvoyant true résoudra votre problème, il désactivera le redimensionnement des colonnes et toutes les colonnes seront redimensionnées pour correspondre au contenu de leurs cellules.
Exemple:
TableView<String[]> table = new TableView<>();
table.setColumnResizePolicy(new Callback<TableView.ResizeFeatures, Boolean>() {
@Override
public Boolean call(ResizeFeatures p) {
return true;
}
});
J'ai utilisé les autres solutions sur cette question et cela fonctionne plutôt bien. Cependant, l'inconvénient est que la largeur de TableView est supérieure à la largeur requise de TableColumns ensemble. J'ai créé un hack pour résoudre ce problème, et cela fonctionne bien:
orderOverview.setColumnResizePolicy((param) -> true );
Platform.runLater(() -> FXUtils.customResize(orderOverview));
où FXUtils.customResize () est créé comme suit:
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()));
}
}
J'espère que cela pourrait être utile pour d'autres personnes aussi!
Ou pour faire court:
// automatically adjust width of columns depending on their content
configAttributeTreeTable.setColumnResizePolicy((param) -> true );
Si vous voulez qu'une seule colonne remplisse la largeur restante d'un tableau, j'ai trouvé une solution assez simple, courte et ne nécessitant pas la solution de réflexion hacky décrite ci-dessus:
DoubleBinding usedWidth = columnA.widthProperty().add(columnB.widthProperty()).add(columnC.widthProperty());
fillingColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(usedWidth));
myTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
for(TableColumn column: myTable.getColumns())
{
column.setMinWidth(200);
}
Ce code redimensionne automatiquement toutes les largeurs de colonne en proportions relationnelles par rapport à la largeur du tableau,
alors qu'il peut fixer la largeur de la première colonne à une valeur donnée lorsque la largeur de la table est inférieure à 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>conseil pour placer le code dans une classe séparée TableAutoresizeModel, vous pourrez y effectuer d'autres calculs, par exemple, en masquant des colonnes, ajoutez un programme d'écoute ...
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);
}