JavaFX TableView прокручивает разные строки, которые не должны быть окрашены - PullRequest
0 голосов
/ 19 марта 2020

Forum,

Я создал Tableview. Каждая строка заполнена информацией, предоставленной каждым объектом «Steckerpin». Используя RowFactory, я окрашиваю фон каждой строки в зависимости от значения атрибута "Zustand" каждого объекта ("Steckerpin").

Проблема в том, что когда таблица становится прокручиваемой, новая появляющаяся строка окрашивается в том же порядке, что и цветные строки в начале. Но эти строки не должны быть цветными, потому что их атрибут "Zustand" не изменился.

Цветные строки перед прокруткой

Новые появляющиеся строки после прокрутки

Если я прокручиваю до конца таблицы, строки неправильного цвета снова становятся белыми.

Я прочитал, что использование таблиц в сочетании с 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);
        }
    }
});

Я прочитал пару похожих вопросов, но не могу найти решение для своей проблемы. Поэтому я был бы очень признателен за помощь.

1 Ответ

1 голос
/ 19 марта 2020

При прокрутке существующие строки повторно используются для отображения новых элементов. Так, например, если у вас была строка, в которой отображался элемент, находившийся в состоянии «ошибка», и он повторно использовался для элемента, находящегося в состоянии «ОК», тогда оба псевдокласса будут установлены на 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)));
    }

});
...