【问题标题】:Combobox doesn't add element with setCellFactory组合框不使用 setCellFactory 添加元素
【发布时间】:2018-06-11 16:45:54
【问题描述】:

我有一个由 10 个组合框组成的数组列表。我想用 n 个图像视图加载每个组合框。

我从一个给我正确数据的类中得到我需要的数据。 您在代码中找到的arraylist 的arraylist 是不同骰子一个接一个的“模拟”,创建不同的列。 例如,我最多有 10 列,每列由 n 个骰子组成。

代码如下:

        //LOADING DICES INTO MY COMBOBOXES
    //List used to load strings  
    ObservableList<String> options = FXCollections.observableArrayList();
    //Arraylist made of arraylist containing the data I need
    ArrayList<ArrayList<Dice>> roundTrackData = gameManager.roundTrack.getDices();
    System.out.println(roundTrackData);
    for(int h=0; h<roundTrackData.size();h++){
        System.out.println(" h Value:" + h);
        ArrayList<Dice> testing = roundTrackData.get(h);
         System.out.println(" Testing:" + testing);
         System.out.println(" Testing size:" + testing.size());


        for(int u=0; u<testing.size();u++){
             System.out.println(" Inside cicle ");

             String color = Character.toString(testing.get(u).getColor());
             String value = testing.get(u).getValue().toString();
             String diceRound = value+color+".png";

             options.add(diceRound);
             //listaComboBox is an array list containing 10 comboboxes
             listaComboBox.get(h).setItems(options);
             listaComboBox.get(h).setCellFactory(c -> new StatusListCell());
             System.out.println("Dice color "+ color);
             System.out.println("Dice value"+ value);
       }
   }

StatusListCell 类:

public class StatusListCell extends ListCell<String> {
protected void updateItem(String item, boolean empty) {
    super.updateItem(item, empty);
    System.out.println("IT'S NULL");

    setGraphic(null);
    setText(null);
    if (item != null) {
        System.out.println("IT'S NOT NULL!");

        ImageView imageView = new ImageView(new Image(item));
        imageView.setFitWidth(40);
        imageView.setFitHeight(40);
        setGraphic(imageView);
        setText("a");
    }
  }
}

我根据这个问题开发了我的代码:JavaFX ComboBox Image

代码工作并将我需要的图像插入我的组合框,问题是它每次都会向每个组合框添加更多图像。

例如:第一个组合框正确加载前 5 个骰子。当我添加其他 5 个骰子(应该只添加到第二个组合框)时,它们会同时添加到第一个和第二个组合框,我会得到两组相同的元素(这一直持续到最后)。

我尝试在第二个周期之前更改我的代码添加options.clear(),因此选项 ObservableList 被重置,我可以从 0 添加我的元素,然后将它们添加到我的h 组合框中。

问题是我实际上没有插入 imageView。

我也尝试过移动

listaComboBox.get(h).setItems(options);
listaComboBox.get(h).setCellFactory(c -> new StatusListCell());

在第二个for 循环中,但我仍然一无所获。

有什么想法吗?我已经尝试了很长时间,但我仍然无法弄清楚真正的问题是什么。

【问题讨论】:

    标签: java javafx combobox


    【解决方案1】:

    您总是添加到同一个列表中。不过,对于不同的项目列表,您需要为每个 ComboBox 使用不同的 ObservableList

    此外,应避免重新加载图像和重新创建ImageViews,以提高程序的效率:

    //Arraylist made of arraylist containing the data I need
    ArrayList<ArrayList<Dice>> roundTrackData = gameManager.roundTrack.getDices();
    System.out.println(roundTrackData);
    final Map<String, WeakReference<Image>> cache = new HashMap<>();
    
    for(int h = 0; h < roundTrackData.size(); h++) {
        ComboBox<String> combo = listaComboBox.get(h);
        combo.setCellFactory(c -> new StatusListCell(cache));
        ObservableList<String> options = FXCollections.observableArrayList();
    
        List<Dice> testing = roundTrackData.get(h);
        System.out.println(" Testing:" + testing);
        System.out.println(" Testing size:" + testing.size());
    
        for(Dice die : testing){
             System.out.println(" Inside cicle ");
             String color = Character.toString(die.getColor());
             String value = die.getValue().toString();
             String diceRound = value+color+".png";
    
             options.add(diceRound);
             //listaComboBox is an array list containing 10 comboboxes
             System.out.println("Dice color "+ color);
             System.out.println("Dice value"+ value);
        }
    
        combo.setItems(options);
    }
    
    public class StatusListCell extends ListCell<String> {
    
        private final Map<String, WeakReference<Image>> cache;
        private final ImageView imageView;
    
        public StatusListCell(Map<String, WeakReference<Image>> cache) {
            imageView = new ImageView();
            imageView.setFitWidth(40);
            imageView.setFitHeight(40);
            setGraphic(imageView); // keep image even if empty for constant cell size
            this.cache = cache;
        }
    
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
    
            if (empty || item == null) {
                setText("");
                imageView.setImage(null); // don't display a image
            } else {
                cache.compute(item, (k, v) -> {
                    // retrieve image or load
                    Image img = null;
                    if (v != null) {
                        img = v.get();
                    }
                    if (img == null) {
                        img = new Image(k);
                        v = new WeakReference<>(img);
                    }
    
                    // change image in imageview
                    imageView.setImage(img);
    
                    return v;
                });
                setText("a");
            }
        }
    
    }
    

    【讨论】:

    • 我重新加载了图像视图,因为原始的 Arraylist 可以从外部修改,因此我的组合框中的内容可能会改变。在这种情况下,您的解决方案是否仍然有效(并且更好)(每次都重新加载图像视图)?
    • @MattiaSurricchio(刚刚在compute 的缺失参数中编辑。)减少Images 的重新加载只是一个优化。 (答案中最不重要的部分之一)。 cache 有机会保留对 Image 的引用。由于它通过 url/constructor 参数存储 Images 并且 Images 在这种情况下可以被认为是不可变的,因此这不应该改变结果(您的原始代码和此代码都可以工作或两者都不起作用) .
    • StatusListCell 的代码说“item”在 'java.fx.Control.Cell' 中有私有访问权限,我说的是新图像(item)中的 item。我该如何解决?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 2016-03-14
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多