当我双击列标题单元格的右边框时,它会自动调整列的宽度。 我如何以编程方式执行相同操作?
答案 0 :(得分:3)
最后我找到了解决方案:
TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (TableColumnHeader columnHeader : rootHeader.getColumnHeaders()) {
try {
TableColumn<?, ?> column = (TableColumn<?, ?>) columnHeader.getTableColumn();
if (column != null) {
Method method = skin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
method.setAccessible(true);
method.invoke(skin, column, 30);
}
} catch (Throwable e) {
e = e.getCause();
e.printStackTrace(System.err);
}
}
Javafx仍然很粗糙。许多简单的事情需要通过深刻的屁股......
答案 1 :(得分:3)
(不仅是内部)API从fx8更改为fx9:
tableViewSkin.getTableHeaderRow()
和tableHeaderRow.getRootHeader()
已从受保护范围更改为包私有范围,合法访问任何内容的唯一方法是通过查找doColumnAutoSize(TableColumnBase, int)
,前提是列的prefWidth的默认值为80.好的一面是:由于这个次优的api,我们可以抓取一个任意的头和自动-size任何列在代码中(注意:这会处理由TableView返回的所有可见叶列,嵌套与否 - 如果要包含隐藏列,则还需要收集它们)
/**
* Resizes all visible columns to fit its content. Note that this does nothing if a column's
* prefWidth is != 80.
*
* @param table
*/
public static void doAutoSize(TableView<?> table) {
// good enough to find an arbitrary column header
// due to sub-optimal api
TableColumnHeader header = (TableColumnHeader) table.lookup(".column-header");
if (header != null) {
table.getVisibleLeafColumns().stream().forEach(column -> doColumnAutoSize(header, column));
}
}
public static void doColumnAutoSize(TableColumnHeader columnHeader, TableColumn column) {
// use your preferred reflection utility method
FXUtils.invokeGetMethodValue(TableColumnHeader.class, columnHeader, "doColumnAutoSize",
new Class[] {TableColumnBase.class, Integer.TYPE},
new Object[] {column, -1});
}
答案 2 :(得分:1)
使用АлександрКиберман发布的上述优秀答案,我创建了一个类来处理这个问题以及getSkin()== null的问题:
import com.sun.javafx.scene.control.skin.NestedTableColumnHeader;
import com.sun.javafx.scene.control.skin.TableColumnHeader;
import com.sun.javafx.scene.control.skin.TableHeaderRow;
import com.sun.javafx.scene.control.skin.TableViewSkin;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.lang.reflect.Method;
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
public class TableViewPlus extends TableView
{
private boolean flSkinPropertyListenerAdded = false;
// ---------------------------------------------------------------------------------------------------------------------
public TableViewPlus()
{
super();
this.setEditable(false);
}
// ---------------------------------------------------------------------------------------------------------------------
public TableViewPlus(final ObservableList toItems)
{
super(toItems);
this.setEditable(false);
}
// ---------------------------------------------------------------------------------------------------------------------
public void resizeColumnsToFit()
{
if (this.getSkin() != null)
{
this.resizeColumnsPlatformCheck();
}
else if (!this.flSkinPropertyListenerAdded)
{
this.flSkinPropertyListenerAdded = true;
// From https://stackoverflow.com/questions/38718926/how-to-get-tableheaderrow-from-tableview-nowadays-in-javafx
// Add listener to detect when the skin has been initialized and therefore this.getSkin() != null.
this.skinProperty().addListener((a, b, newSkin) -> this.resizeColumnsPlatformCheck());
}
}
// ---------------------------------------------------------------------------------------------------------------------
private void resizeColumnsPlatformCheck()
{
if (Platform.isFxApplicationThread())
{
this.resizeAllColumnsUsingReflection();
}
else
{
Platform.runLater(this::resizeAllColumnsUsingReflection);
}
}
// ---------------------------------------------------------------------------------------------------------------------
// From https://stackoverflow.com/questions/38090353/javafx-how-automatically-width-of-tableview-column-depending-on-the-content
// Geesh. . . .
private void resizeAllColumnsUsingReflection()
{
final TableViewSkin<?> loSkin = (TableViewSkin<?>) this.getSkin();
// The skin is not applied till after being rendered. Which is happening with the About dialog.
if (loSkin == null)
{
System.err.println("Skin is null");
return;
}
final TableHeaderRow loHeaderRow = loSkin.getTableHeaderRow();
final NestedTableColumnHeader loRootHeader = loHeaderRow.getRootHeader();
for (final TableColumnHeader loColumnHeader : loRootHeader.getColumnHeaders())
{
try
{
final TableColumn<?, ?> loColumn = (TableColumn<?, ?>) loColumnHeader.getTableColumn();
if (loColumn != null)
{
final Method loMethod = loSkin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
loMethod.setAccessible(true);
loMethod.invoke(loSkin, loColumn, 30);
}
}
catch (final Throwable loErr)
{
loErr.printStackTrace(System.err);
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
}
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
答案 3 :(得分:0)
table.skinProperty().addListener((a, b, newSkin) -> {
TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (TableColumnHeader columnHeader : rootHeader.getColumnHeaders()) {
try {
TableColumn<?, ?> column = (TableColumn<?, ?>) columnHeader.getTableColumn();
if (column != null) {
Method method = skin.getClass().getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
method.setAccessible(true);
method.invoke(skin, column, 30);
}
} catch (Throwable e) {
e = e.getCause();
e.printStackTrace(System.err);
}
}
});
为了防止getSkin()== null;