为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

回首忆惘然 2023-05-10 14:20:17
我试图通过尝试显示彩色矩形而不是字符串本身来自定义 Javafx 中的 ListView。public class Main extends Application {@Overridepublic 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 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

itema 的属性最初ListCellnullColor.web不接受null作为参数。此外,您需要能够处理这样一个事实,即 a 的项目ListCell可以在其生命周期内被替换,并且相同的项目可以分配给不同的单元格。ListView只创建填充视图所需的单元格,如果例如可滚动区域的视口发生变化,则需要显示不同的项目,并且单元格被重用以显示更改后的项目集。

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

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

  1. Color.web不贵,

  2. 命名的颜色,比如你使用的项目,Map无论如何都存储在一个地方;Color无论将相同参数传递给 . 的频率如何,每种不同的命名颜色都只会创建一个实例Color.web

顺便说一句:我不建议以不能成为调用结果的方式初始化单元格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);

        }

    }

}


查看完整回答
反对 回复 2023-05-10
  • 1 回答
  • 0 关注
  • 106 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信