JavaFX ListView中出现神秘的“必须指定颜色组件或名称”错误

时间:2019-07-31 15:29:31

标签: java javafx desktop-application

我试图通过尝试显示彩色矩形而不是字符串本身来自定义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的行中。我稍微操纵了细胞班,它奏效了。下面是操纵单元格类:

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()完成的工作,但是由于某种原因,它在该行中引发了错误。前一种方法出错的原因可能是什么

1 个答案:

答案 0 :(得分:1)

item的{​​{1}}属性最初是ListCellnull不接受Color.web作为参数。此外,您需要能够处理以下事实:null的项目可以在其生命周期内被替换,并且同一项目可以分配给不同的单元格。 ListCell仅创建填充视图所需的单元格,例如可滚动区域的视口发生变化,需要显示不同的项目,并且单元格被重新使用以显示更改后的项目集。

如果您担心ListView中某些计算的性能,可以将结果缓存在映射中(如果担心内存消耗,可以将值包装在updateItem中)。

在这种情况下,这是不必要的,因为:

  1. SoftReference并不昂贵,
  2. 已命名的颜色(如您使用的物品)始终存储在Color.web中;不论您将相同参数传递给Map的频率如何,每种不同的命名颜色只会创建一个Color实例。

顺便说一句:我不建议以无法通过Color.web调用的结果来初始化单元格。在您的情况下,除了初始状态外,空白单元格的updateItem属性为graphic。如果您担心单元格大小的一致性,最好始终保留图形并设置其可见性:

null