我一直在试图弄清楚如何自动调整TreeView列的大小以适应他们的内容一段时间。之前已经提出这个问题,但反应很小,不可接受。
[javafx column in tableview auto fit size
奇怪的是,我正在寻找的行为正是您在TableView中双击列调整大小行时所发生的情况。但是,在查看JavaFX源代码时,我一直无法弄清楚这是如何发生的。
有没有人知道在JavaFX TableView / TableColumn / TableColumnHeader中处理列调整大小行上的双击行为的方式/位置?
如果可能的话,我只想让列首先自动执行渲染双击调整大小行时会发生什么。这是如何已经不存在的预先创建的列大小约束策略之一。
答案 0 :(得分:6)
适用于JavaFX8的解决方案:
将columnResizePolciy
设置为CONSTRAINED_RESIZE_POLICY
<TableView fx:id="table" >
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
答案 1 :(得分:3)
这是我为JavaFX 2.2提出的最终解决方案,它现在也考虑了列标题的宽度:
/**
* Auto-sizes table view columns to fit its contents.
*
* @note This is not a column resize policy and does not prevent manual
* resizing after this method has been called.
* @param tableView
* The table view in which to resize all columns.
*/
public static void autoSizeTableViewColumns(final TableView<?> tableView)
{
autoSizeTableViewColumns(tableView, -1, -1);
}
/**
* Auto-sizes table view columns to fit its contents.
*
* @note This is not a column resize policy and does not prevent manual
* resizing after this method has been called.
*
* @param tableView
* The table view in which to resize all columns.
* @param minWidth
* Minimum desired width of text for all columns.
* @param maxWidth
* Maximum desired width of text for all columns.
*/
public static void autoSizeTableViewColumns(final TableView<?> tableView, int minWidth, int maxWidth)
{
TableViewSkin<?> skin = (TableViewSkin<?>) tableView.getSkin();
if (skin == null)
{
AppLogger.getLogger().warning(tableView + " skin is null.");
return;
}
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (Node node : rootHeader.getChildren())
{
if (node instanceof TableColumnHeader)
{
TableColumnHeader columnHeader = (TableColumnHeader) node;
try
{
autoSizeTableViewColumn(columnHeader, minWidth, maxWidth, -1);
}
catch (Throwable e)
{
e = e.getCause();
AppLogger.getLogger().log(Level.WARNING, "Unable to automatically resize tableView column.", e);
}
}
}
}
/**
* Auto-sizes table view columns to fit its contents.
*
* @note This is not a column resize policy and does not prevent manual
* resizing after this method has been called.
*
* @param col
* The column to resize.
* @param minWidth
* Minimum desired width of text for this column. Use -1 for no minimum
* width.
* @param maxWidth
* Maximum desired width of text for this column. Use -1 for no maximum
* width.
* @param maxRows
* Maximum number of rows to examine for auto-resizing. Use -1
* for all rows.
*/
public static void autoSizeTableViewColumn(TableColumn<?,?> column, int minWidth, int maxWidth, int maxRows)
{
TableView<?> tableView = column.getTableView();
TableViewSkin<?> skin = (TableViewSkin<?>) tableView.getSkin();
if (skin == null)
{
AppLogger.getLogger().warning(tableView + " skin is null.");
return;
}
TableHeaderRow headerRow = skin.getTableHeaderRow();
NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
for (Node node : rootHeader.getChildren())
{
if (node instanceof TableColumnHeader)
{
TableColumnHeader columnHeader = (TableColumnHeader) node;
if(columnHeader.getTableColumn().equals(column))
{
autoSizeTableViewColumn(columnHeader, minWidth, maxWidth, maxRows);
}
}
}
}
/**
* Auto-sizes a table view column to fit its contents.
*
* @note This is not a column resize policy and does not prevent manual
* resizing after this method has been called.
*
* @param col
* The column to resize.
* @param minWidth
* Minimum desired width of text for this column. Use -1 for no minimum
* width.
* @param maxWidth
* Maximum desired width of text for this column. Use -1 for no maximum
* width.
* @param maxRows
* Maximum number of rows to examine for auto-resizing. Use -1
* for all rows.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void autoSizeTableViewColumn(TableColumnHeader header, int minWidth, int maxWidth, int maxRows)
{
TableColumn<?, ?> col = header.getTableColumn();
if(col != null)
{
List<?> items = col.getTableView().getItems();
if (items == null || items.isEmpty())
return;
Callback cellFactory = col.getCellFactory();
if (cellFactory == null)
return;
TableCell cell = (TableCell) cellFactory.call(col);
if (cell == null)
return;
// set this property to tell the TableCell we want to know its actual
// preferred width, not the width of the associated TableColumn
cell.getProperties().put("deferToParentPrefWidth", Boolean.TRUE);
// determine cell padding
double padding = 10;
Node n = cell.getSkin() == null ? null : cell.getSkin().getNode();
if (n instanceof Region)
{
Region r = (Region) n;
padding = r.getInsets().getLeft() + r.getInsets().getRight();
}
int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows);
double desiredWidth = 0;
// Check header
Label headerLabel = (Label) header.lookup(".label");
String headerText = headerLabel.getText();
if (!headerLabel.getContentDisplay().equals(ContentDisplay.GRAPHIC_ONLY) && headerText != null)
{
Text text = new Text(headerLabel.getText());
text.setFont(headerLabel.getFont());
desiredWidth += text.getLayoutBounds().getWidth() + headerLabel.getLabelPadding().getLeft() + headerLabel.getLabelPadding().getRight();
}
Node headerGraphic = headerLabel.getGraphic();
if((headerLabel.getContentDisplay().equals(ContentDisplay.LEFT) || headerLabel.getContentDisplay().equals(ContentDisplay.RIGHT)) && headerGraphic != null)
{
desiredWidth += headerGraphic.getLayoutBounds().getWidth();
}
// Handle minimum width calculations
// Use a "w" because it is typically the widest character
Text minText = new Text(StringUtils.repeat("W", Math.min(0, minWidth)));
minText.setFont(headerLabel.getFont());
// Check rows
double minPxWidth = 0;
for (int row = 0; row < rows; row++)
{
cell.updateTableColumn(col);
cell.updateTableView(col.getTableView());
cell.updateIndex(row);
// Handle minimum width calculations
// Just do this once
if(row == 0)
{
String oldText = cell.getText();
// Use a "w" because it is typically the widest character
cell.setText(StringUtils.repeat("W", Math.max(0, minWidth)));
header.getChildren().add(cell);
cell.impl_processCSS(false);
minPxWidth = cell.prefWidth(-1);
header.getChildren().remove(cell);
cell.setText(oldText);
}
if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null)
{
header.getChildren().add(cell);
cell.impl_processCSS(false);
desiredWidth = Math.max(desiredWidth, cell.prefWidth(-1));
desiredWidth = Math.max(desiredWidth, minPxWidth);
header.getChildren().remove(cell);
}
}
desiredWidth = desiredWidth + padding;
if(maxWidth > 0)
{
desiredWidth = Math.min(maxWidth, desiredWidth);
}
col.impl_setWidth(desiredWidth);
}
}
请记住,这是&#34;黑客攻击&#34;受保护的方法,可以随时使用JavaFX更新进行更改并破坏方法。我相信这已经在JavaFX 8中发生了变化。这也可能会因应用程序签署部署的方式而中断。
它不是很漂亮,但是JavaFX隐藏了这个功能,所以除非你想重新实现整个功能,否则这是我发现的最佳方法。
答案 2 :(得分:3)
您的代码中有一些缺失的部分,例如obj未声明。我也找不到你在该课程中任何地方使用的方法。我正在使用1.8.0_20-ea-b05,或者反过来告诉我。我在TableViewSkin中找到了类似的方法。
public static void autoSizeTableViewColumns(final TableView<?> tableView) {
TableViewSkin<?> skin = (TableViewSkin<?>) tableView.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);
}
}
}