添加到 observableList 时渲染项目的 JavaFX listview 重复

JavaFX listview duplication of rendered items when added to observableList

我有一个附加了 observableList 的 ListView,

@FXML
private ListView<Weapon> listViewWeapons;

  .... 
  //initialize
  listViewWeapons.setCellFactory(lv -> new CustomWeaponDetailListCell<>());
  listViewWeapons.setItems(CsgoRr.getModel().getWeaponCache());

自定义单元格:

public class CustomWeaponDetailListCell<T extends Weapon> extends ListCell<T> {

    private final StringBuilder sb = new StringBuilder();

    @Override
    public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setText(null);
        } else {
            sb.append(item.getName()).append("    Detail:")
                    .append((String) CsgoRr.objectToJsonString(item.getRecoilPattern()));

            setText(sb.toString());
        }
    }
}

创建新武器并将其添加到数据库和列表的函数:

private static int newWeaponNameIncrement = 1;

@FXML
private void newWeaponOnAction() {
    try {
        System.out.println("DEBUG WEAPON NAME TRYING TO BE CREATED IS :" + "newWeapon" + newWeaponNameIncrement);
        Weapon newWeapon = Weapon.createWeapon("newWeapon" + newWeaponNameIncrement,
                new RecoilPattern());
        newWeapon.setId(DbUtil.storeWeapon(newWeapon));

        CsgoRr.getModel().getWeaponCache().add(newWeapon);
    } catch (SQLException ex) {
        if (ex.getErrorCode() == 23505) {//duplicate name
            System.out.println("DEBUG :Duplicate name on add new weapon");
            newWeaponNameIncrement++;
            newWeaponOnAction();
        }

        Logger.getLogger(WeaponViewController.class.getName()).log(Level.SEVERE, null, ex);
    } catch (AWTException ex) {
        Logger.getLogger(WeaponViewController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

一切正常,数据已添加到数据库中,但问题又出在我如何看待 listView behave.The 问题已得到证明 here in a GIF(GIF 有点太大,您有单击 link,无法将其嵌入此处)。

正如您从图片中看到的那样,问题在于它至少在视觉上重复了列表中的项目,因此更改会刷新,但不是以正确的方式。一旦我将视图更改为其他内容然后返回,调用构造函数和初始化方法,一切看起来都应该如此。任何人都知道这是什么问题?

奇怪的是我在其他控制器中有类似的代码,它指向我之前的 SO 问题,我没有解决任何问题并且工作完美,但是当我以几乎相同的方式执行此操作时,我在这里得到不同的结果。 这是一个不同的问题,之前我没有任何更新反馈,现在我有反馈,但不是正确的反馈。

每次交换项目而不清除它时,您都会重复使用相同的 StringBuilder。这意味着生成的 String 将是存储在 Cell.

中的项目的所有值的串联

您需要每次使用不同的StringBuilder或清除StringBuilder:

public class CustomWeaponDetailListCell<T extends Weapon> extends ListCell<T> {

    private final StringBuilder sb = new StringBuilder();

    @Override
    public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setText(null);
        } else {
            sb.append(item.getName()).append("    Detail:")
                    .append((String) CsgoRr.objectToJsonString(item.getRecoilPattern()));

            setText(sb.toString());

            // clear StringBuilder content
            sb.delete(0, sb.length());
        }
    }
}