java - JavaFX ListView 中神秘的 "The color components or name must be specified "错误

标签 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);
}

}

显然错误出现在我指示为“错误”的行中。我对单元格类做了一些操作,它起作用了。下面是被操纵的单元格类:

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

最佳答案

ListCellitem 属性最初为 nullColor.web 不接受 null 作为参数。此外,您需要能够处理以下事实:ListCell 的项目可以在其生命周期内替换,并且相同的项目可以分配给不同的单元格。 ListView 仅创建填充 View 所需的单元格,例如可滚动区域的视口(viewport)发生变化,需要显示不同的项目,并且重用单元格来显示更改后的项目集。

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

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

  1. Color.web 并不昂贵,
  2. 无论如何,命名颜色(例如您使用的项目)都存储在 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);
        }
    }
}

关于java - JavaFX ListView 中神秘的 "The color components or name must be specified "错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57294287/

相关文章:

java - 如何分发 java GUI 构建器项目

webview - 在 Webview/中禁用自动图像加载

wpf - 为什么 WPF 会随着 Silverlight 4 的到来而失去地形?

java - 是否有任何 Java 内核/桌面应用程序?

java - 无法使用 GCM 获取我的 InstanceID

java - 我的 PIRC 机器人代码做错了什么?

java - 需要帮助理解遍历二叉搜索树方法

listview - 在JavaFX中更新ListView时出现IndexOutOfBoundsException

css - 如何在 JavaFX 中使用后备字体?

java - 使用 google+ 的 api key 从 java 中的桌面应用程序发出请求