JavaFX ListView 中神秘的“必须指定颜色组件或名称”错误
Mysterious " The color components or name must be specified " error in JavaFX ListView
我试图通过显示彩色矩形而不是字符串本身来自定义 Javafx 中的 ListView。
public class Main extends Application {
@Override
public void start(Stage primaryStage)
{
VBox vBox = new VBox();
ListView<String> listView = new ListView<>();
vBox.getChildren().add(listView);
ObservableList<String> list = FXCollections.observableArrayList("black" , "blue" , "brown" , "gold");
listView.setItems(list);
listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> stringListView) {
return new cell();
}
});
primaryStage.setScene(new Scene(vBox,400 , 400));
primaryStage.show();
}
public class cell extends ListCell<String>
{
Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
this.rect.setFill(Color.web(getItem())); // ERROR ERROR ERROR
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
setGraphic(null);
else
setGraphic(this.rect);
}
}
public static void main(String[] args) {
launch(args);
}
}
显然错误出现在我指出为 ERROR 的行中。我稍微操纵了单元格 class,它起作用了。下面是被操作的单元格 class:
public class cell extends ListCell<String>
{
Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
// this.rect.setFill(Color.web(getItem()));
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
setGraphic(null);
else {
rect.setFill(Color.web(getItem()));
setGraphic(this.rect);
}
}
我知道 updateItem() 将被调用很多次。我的第一个方法确实减少了 updateItem() 完成的工作,但由于某种原因它在该行中抛出错误。之前的方法出错的原因可能是什么
一个ListCell
的item
属性最初是null
。 Color.web
不接受 null
作为参数。此外,您需要能够处理这样一个事实,即 ListCell
的项目可以在其生命周期内被替换,并且相同的项目可以分配给不同的单元格。 ListView
仅创建填充视图所需的单元格,例如可滚动区域的视口发生变化,需要显示不同的项目,并重新使用单元格来显示更改后的项目集。
如果您担心 updateItem
中某些计算的性能,您可以将结果缓存在映射中(如果您担心内存消耗,可能会将值包装在 SoftReference
中).
在这种情况下,这是没有必要的,因为:
Color.web
不贵,
- 命名的颜色,例如您使用的物品,无论如何都存储在
Map
中;无论您将相同参数传递给 Color.web
. 的频率如何,每个不同的命名颜色只会创建一个 Color
实例
顺便说一句:我不建议以不能成为 updateItem
调用结果的方式初始化单元格。在您的情况下,空单元格的 graphic
属性 是 null
除了初始状态。如果您担心一致的单元格大小,最好始终保留图形并设置其可见性:
public class cell extends ListCell<String> {
private final Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
rect.setVisible(false);
else {
rect.setFill(Color.web(getItem()));
rect.setVisible(true);
}
}
}
我试图通过显示彩色矩形而不是字符串本身来自定义 Javafx 中的 ListView。
public class Main extends Application {
@Override
public void start(Stage primaryStage)
{
VBox vBox = new VBox();
ListView<String> listView = new ListView<>();
vBox.getChildren().add(listView);
ObservableList<String> list = FXCollections.observableArrayList("black" , "blue" , "brown" , "gold");
listView.setItems(list);
listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> stringListView) {
return new cell();
}
});
primaryStage.setScene(new Scene(vBox,400 , 400));
primaryStage.show();
}
public class cell extends ListCell<String>
{
Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
this.rect.setFill(Color.web(getItem())); // ERROR ERROR ERROR
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
setGraphic(null);
else
setGraphic(this.rect);
}
}
public static void main(String[] args) {
launch(args);
}
}
显然错误出现在我指出为 ERROR 的行中。我稍微操纵了单元格 class,它起作用了。下面是被操作的单元格 class:
public class cell extends ListCell<String>
{
Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
// this.rect.setFill(Color.web(getItem()));
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
setGraphic(null);
else {
rect.setFill(Color.web(getItem()));
setGraphic(this.rect);
}
}
我知道 updateItem() 将被调用很多次。我的第一个方法确实减少了 updateItem() 完成的工作,但由于某种原因它在该行中抛出错误。之前的方法出错的原因可能是什么
一个ListCell
的item
属性最初是null
。 Color.web
不接受 null
作为参数。此外,您需要能够处理这样一个事实,即 ListCell
的项目可以在其生命周期内被替换,并且相同的项目可以分配给不同的单元格。 ListView
仅创建填充视图所需的单元格,例如可滚动区域的视口发生变化,需要显示不同的项目,并重新使用单元格来显示更改后的项目集。
如果您担心 updateItem
中某些计算的性能,您可以将结果缓存在映射中(如果您担心内存消耗,可能会将值包装在 SoftReference
中).
在这种情况下,这是没有必要的,因为:
Color.web
不贵,- 命名的颜色,例如您使用的物品,无论如何都存储在
Map
中;无论您将相同参数传递给Color.web
. 的频率如何,每个不同的命名颜色只会创建一个
Color
实例
顺便说一句:我不建议以不能成为 updateItem
调用结果的方式初始化单元格。在您的情况下,空单元格的 graphic
属性 是 null
除了初始状态。如果您担心一致的单元格大小,最好始终保留图形并设置其可见性:
public class cell extends ListCell<String> {
private final Rectangle rect;
cell() {
super();
this.rect = new Rectangle(20,20);
setGraphic(this.rect);
}
@Override
protected void updateItem(String s, boolean empty) {
super.updateItem(s, empty);
if(empty)
rect.setVisible(false);
else {
rect.setFill(Color.web(getItem()));
rect.setVisible(true);
}
}
}