我正在创建一个highlighting communication logger,它使用ListView
在单个单元格中显示每条消息。
它基本上有效,但当我上下快速滚动时,会发生奇怪的事情。如您所见,我突出显示当前所选的单元格和鼠标所在的单元格。在我上下滚动后,突出显示的单元格不是我的鼠标指针所在的单元格,对于某些单元格,我无法通过单击选择它们。
我能够在一个非常简单的例子中重现这一点。假设我们有ListView
个字符串,其中包含自定义MyListCell
,可使用TextFlow
呈现这些单元格。 updateItem
的{{1}}方法看起来像这样
MyListCell
在初始化中我只是创建一个新的可观察字符串数组,并相应地设置单元格工厂:
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
return;
}
TextFlow textFlow = new TextFlow(new Text(item));
setGraphic(textFlow);
setText(null);
}
完整的工作示例代码仅包含一些文件(您需要调整包路径):
问题:任何人都可以确认这种行为并告诉我我做错了什么吗?
我的系统是Ubuntu 14.04,带有Oracle jdk 1.8.0_25
答案 0 :(得分:3)
基本上在JavaFX中创建一个新的Node
并将其添加到SceneGraph是一项昂贵的操作。这就是为什么ListView
使用虚拟化布局容器,在视口更改时重用其单元格而不是创建新单元格。
您应该重复使用TextFlow
内的ListCell
或换句话说:将其存储为会员属性,并且仅保留""将其子项设置在updateItem()
方法中。
关于TextFlow
vs HBox
:由于内置(单词)换行,TextFlow
具有相当复杂的布局机制。因此,如果HBox
完成了您的需要,您应该考虑使用它(当然在ListCell中缓存它)。
您可以尝试缓存Text
节点,以进一步提升此功能。但是目前我无法为您提供一个简单的解决方案(JavaFX中的Node
只能包含在一个Parent
节点中,所以一个简单的WeakHashMap
缓存带有computeIfAbsent
不会工作)..