添加到 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());
}
}
}
我有一个附加了 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());
}
}
}