afaik javafxのTableViewには、CONSTRAINED_RESIZE_POLICYとUNCONSTRAINED_RESIZE_POLICYの2つの列サイズ変更ポリシーがありますが、セルの内容に合わせて列のサイズを変更したいのですが、他のプラットフォーム(C#のdatagridviewなど)では単純な問題だと思いますが、解決できません
15 に答える
3年後、私は再びこの問題に戻ってきました.いくつかの提案は、各セル内のデータのテキストのサイズを計算しています(フォントサイズ、フォントファミリ、パディングによっては複雑です...)
しかし、テーブル ヘッダーの仕切りをクリックすると、必要に応じてコンテンツに合わせてサイズが変更されることに気付きました。そこで、JavaFX ソース コードを掘り下げて、最終的に TableViewSkin の resizeColumnToFitContent メソッドを見つけましたが、これは保護されたメソッドであり、リフレクションによって解決できます。
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()の後にこの関数を呼び出す必要があります。
true を返すコールバック関数をオーバーライドするだけで問題が解決し、列のサイズ変更が無効になり、すべての列がセルの内容に合わせてサイズ変更されると思います。
例:
TableView<String[]> table = new TableView<>();
table.setColumnResizePolicy(new Callback<TableView.ResizeFeatures, Boolean>() {
@Override
public Boolean call(ResizeFeatures p) {
return true;
}
});
この質問に対して他のソリューションを使用しましたが、かなりうまく機能します。ただし、これの欠点は、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()));
}
}
これが他の人にも役立つことを願っています!
TreeTableView のソリューションを実装しました。まだ進化の途中ですが、有望な結果を示しています。以下、解決策の説明です。
コントロール スキン クラスでは、コントロールの子に TreeTableView と非表示の VBox を追加しました。セル ファクトリは、派生セルをターゲット TreeTableColumn に提供します。派生セルは、空のプロパティに従って非表示の VBox に追加または削除される Label ノードをラップし、その prefWidth はセル幅に従って設定されます。セルは以下を利用します。
getProperties().put(Properties.DEFER_TO_PARENT_PREF_WIDTH, Boolean.TRUE)
次のように、セルの computePrefWidth() メソッドをオーバーライドします。
@Override
protected double computePrefWidth(double height) {
return Double.max(_box.prefWidth(-1.0), super.computePrefWidth(height) + 24.0);
}
Vbox 幅プロパティは、TreeTableColumn の prefWidth にバインドされます。これは、列のヘッダーのサイズ変更にも必要です。
現時点では、ソリューションの開発を簡素化するために、このアプローチは、組み込みの並べ替え、並べ替え、およびサイズ変更機能を無効にしてもうまく機能することに注意してください。すなわち。
_nameColumn = new TreeTableColumn<>("Name");
_nameColumn.setResizable(false);
_nameColumn.setReorderable(false);
_nameColumn.setSortable(false);
ハッピーコーディング
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);
}