JavaFX TableView 滚动为不同的行着色,这些行不应该被着色

JavaFX TableView scrolling colors different row that aren't ment to be colored

论坛,

我创建了一个 Tableview。每行都填充了每个 "Steckerpin" 对象提供的信息。使用 RowFactory,我根据每个对象 ("Steckerpin") 的属性值 "Zustand" 为每一行的背景着色。

问题是,当 table 变为可滚动时,新出现的行的颜色顺序与开头的彩色行的顺序相似。但是这些行不应该是彩色的,因为它们的属性 "Zustand" 没有改变。

Colored rows before scrolling

New appearing rows after scrolling

如果我滚动到 table 的末尾,错误的彩色行再次变为白色。

我了解到,将 table 视图与 RowFactory 结合使用是一个常见问题,因为一旦开始滚动,行就会被重复使用。

这是我使用 RowFactory 的代码:

durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {

    @Override
    public void updateItem(Steckerpin item, boolean empty) {
        super.updateItem(item, empty);

        if (item == null || empty) {
            setGraphic(null);
            setStyle("");
        } else if (item.getZustand().equals(okZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), true);
        } else if (item.getZustand().equals(fehlerZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), true);
        } else if (item.getZustand().equals(prüfZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), true);
        }
    }
});

我已经阅读了几个类似的问题,但找不到解决我的问题的方法。所以我将非常感谢您的帮助。

滚动时,现有行将重新用于显示新项目。因此,例如,如果您有一行显示处于 "error" 状态的项目,并且它被重新用于处于 "ok" 状态的项目,那么两个伪类都将设置为true.

因此,您需要在所有条件下将所有伪类设置为正确的状态:

durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {

    @Override
    public void updateItem(Steckerpin item, boolean empty) {
        super.updateItem(item, empty);

        if (item == null || empty) {
            setGraphic(null);
            setStyle("");
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
        } else if (item.getZustand().equals(okZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), true);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
        } else if (item.getZustand().equals(fehlerZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), true);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
        } else if (item.getZustand().equals(prüfZustString)) {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), true);
        } else {
            pseudoClassStateChanged(PseudoClass.getPseudoClass("ok"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("error"), false);
            pseudoClassStateChanged(PseudoClass.getPseudoClass("pending"), false);
        }
    }
});

等价,代码更少:

durchgangsTable.setRowFactory(tv -> new TableRow<Steckerpin>() {

    private final List<String> states = List.of("ok", "error", "pending");

    @Override
    public void updateItem(Steckerpin item, boolean empty) {
        super.updateItem(item, empty);

        if (item == null || empty) {
            setGraphic(null);
            setStyle("");
            updateState(null);
        } else if (item.getZustand().equals(okZustString)) {
            updateState("ok");
        } else if (item.getZustand().equals(fehlerZustString)) {
            updateState("error");
        } else if (item.getZustand().equals(prüfZustString)) {
            updateState("pending");
        } else {
            updateState(null);
        }
    }

    private void updateState(String newState) {
        states.forEach(state ->
            pseudoClassStateChanged(PseudoClass.getPseudoClass(state), state.equals(newState)));
    }

});