猿问

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 的行中。我稍微操纵了细胞类,它起作用了。下面是被操纵的细胞类:


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


回首忆惘然
浏览 108回答 1
1回答

暮色呼如

itema 的属性最初ListCell是null。Color.web不接受null作为参数。此外,您需要能够处理这样一个事实,即 a 的项目ListCell可以在其生命周期内被替换,并且相同的项目可以分配给不同的单元格。ListView只创建填充视图所需的单元格,如果例如可滚动区域的视口发生变化,则需要显示不同的项目,并且单元格被重用以显示更改后的项目集。如果您担心 中某些计算的性能updateItem,您可以将结果缓存在映射中(如果SoftReference您担心内存消耗,可以将值包装在 s 中)。在这种情况下,这是没有必要的,因为:Color.web不贵,命名的颜色,比如你使用的项目,Map无论如何都存储在一个地方;Color无论将相同参数传递给 . 的频率如何,每种不同的命名颜色都只会创建一个实例Color.web。顺便说一句:我不建议以不能成为调用结果的方式初始化单元格updateItem。在您的情况下,graphic空单元格的属性不null包括初始状态。如果您担心一致的单元格大小,最好始终保留图形并设置其可见性:public class cell extends ListCell<String> {&nbsp; &nbsp; private final Rectangle rect;&nbsp; &nbsp; cell() {&nbsp; &nbsp; &nbsp; &nbsp; super();&nbsp; &nbsp; &nbsp; &nbsp; this.rect = new Rectangle(20,20);&nbsp; &nbsp; &nbsp; &nbsp; setGraphic(this.rect);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void updateItem(String s, boolean empty) {&nbsp; &nbsp; &nbsp; &nbsp; super.updateItem(s, empty);&nbsp; &nbsp; &nbsp; &nbsp; if(empty)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect.setVisible(false);&nbsp; &nbsp; &nbsp; &nbsp; else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect.setFill(Color.web(getItem()));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect.setVisible(true);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答