JavaFX 9/10 不再可能覆盖 TableView.resizeColumnToFitContent
Posted
技术标签:
【中文标题】JavaFX 9/10 不再可能覆盖 TableView.resizeColumnToFitContent【英文标题】:JavaFX 9/10 no longer possible to override TableView.resizeColumnToFitContent 【发布时间】:2018-11-08 01:59:19 【问题描述】:在 JavaFX 8 中,可以覆盖 TableView.resizeColumnToFitContent
函数。这对我们的目的至关重要,因为它允许我们在默认实现之外增强列标题的布局方式,以及在较大的表中调整默认值的性能。
如何增强布局行为的一个例子是在嵌套列标题的上下文中。默认情况下,叶列标题的 prefWidth 根据该列中数据行的最大宽度或叶列标题文本的宽度设置,以较大者为准。但是,如果该叶子标题有一些父列标题具有更宽的标题文本,它们将被剪裁并显示一个省略号。这对我们来说是不可取的,因此我们更改了resizeColumnToFitContent
,因此叶列标题的 prefWidth 也考虑了其父列标题的 prefWidth。
从 Java 9 和以下提交开始,resizeColumnToFitContent
函数已移至静态位置,从而无法自定义此行为:
http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/53bfdfed5bbf
大约一周前,我写信给负责此更改的作者 Jonathan Giles,但我猜他是个忙碌的人,这正在成为我们以及我们将产品迁移到 Java 10 的计划的阻碍问题,所以我想我还想看看社区是否知道我可以如何解决这个问题。到目前为止,唯一的选择似乎是有点蛮力的方法outlined here,但也许有更好的方法?
【问题讨论】:
FWIW,乔纳森不再为甲骨文工作。这种方法实际上从来都不是公共 API 的一部分,是吗? James 是对的——我不再在 Oracle 工作,也不再负责那里的任何代码 :-) 我建议你采取蛮力方法——这基本上就是你想要公开的代码所做的无论如何(从记忆中) 为什么这个函数不能成为受保护 API 的一部分? TableView 是 JavaFX 中的核心控件,应该尽可能地扩展,而不必诉诸蛮力。你认为值得我花时间向 OpenJDK 提交 PR 来实现吗? 基本上,继承在某种程度上破坏了封装,因为要覆盖一个方法,您必须了解该方法的实现。这意味着如果 API 允许重写某个方法,那么它将始终将该 API 提交给该特定实现。当皮肤类在 Java 9 中移至公共 API 时,一些方法被设为私有(或移至实用程序类);大概这些是 JavaFX 团队尚未准备好提交所使用的特定实现的方法。如果您还没有,请阅读 Josh Bloch 的“Effective Java”。 James 是对的(再次)——API 设计的最佳方法是缓慢而谨慎。制作一个“尽可能可扩展”的 API 是一件非常困难的事情,因为这意味着我们基本上只是将整个实现公开,这使我们永远无法更改与代码相关的任何内容,因为这意味着我们可能会破坏某人。这就是为什么首先将 API 和实现的概念分开的原因 - 像这里所做的那样依赖实现是不明智的,因为不能保证它会保持稳定。 【参考方案1】:如果你想重写这个方法,为什么你不实现你自己的 resizeColumnToFitContent 就像在 TableSkinUtils 中那样?
【讨论】:
该方法是从其中一个皮肤类(TableColumnHeader
,也许还有其他)中的private
方法调用的,因此您不能覆盖调用它的方法。因此,可能是设计使然,没有办法重新定义这种行为。 (你基本上最终会从头开始重新实现几乎所有的皮肤。)
@James_D 确实是这样,有许多相关的类需要重新实现【参考方案2】:
借助 Java 16,我们现在可以以新的方式访问 resizeColumnToFitContent
class FitWidthTableView<T> extends TableView<T>
public FitWidthTableView()
setSkin(new FitWidthTableViewSkin<>(this));
public void resizeColumnsToFitContent()
Skin<?> skin = getSkin();
if (skin instanceof FitWidthTableViewSkin<?> ctvs) ctvs.resizeColumnsToFitContent();
class FitWidthTableViewSkin<T> extends TableViewSkin<T>
public FitWidthTableViewSkin(TableView<T> tableView)
super(tableView);
@Override
protected TableHeaderRow createTableHeaderRow()
return new TableHeaderRow(this)
@Override
protected NestedTableColumnHeader createRootHeader()
return new NestedTableColumnHeader(null)
@Override
protected TableColumnHeader createTableColumnHeader(TableColumnBase col)
return new FitWidthTableColumnHeader(col);
;
;
public void resizeColumnsToFitContent()
for (TableColumnHeader columnHeader : getTableHeaderRow().getRootHeader().getColumnHeaders())
if (columnHeader instanceof FitWidthTableColumnHeader colHead) colHead.resizeColumnToFitContent(-1);
class FitWidthTableColumnHeader extends TableColumnHeader
public FitWidthTableColumnHeader(TableColumnBase col)
super(col);
@Override
public void resizeColumnToFitContent(int rows)
super.resizeColumnToFitContent(-1);
【讨论】:
以上是关于JavaFX 9/10 不再可能覆盖 TableView.resizeColumnToFitContent的主要内容,如果未能解决你的问题,请参考以下文章
为啥嵌入 UINavigationController 时不再显示 UITableView