Обновление внешнего вида строки TableView

У меня есть некоторые трудности, чтобы изменить внешний вид некоторых строк TableView. В строке должен отображаться текст с обводкой и красным цветом. На самом деле, я могу показать это красным цветом, но все еще не могу сделать удар. Это класс css, который я использую для изменения внешнего вида строки:

.itemCancelado {
    -fx-strikethrough: true;
    -fx-text-fill: red;
}

Этот класс стиля добавляется, когда пользователь помечает элемент как отмененный:

public class ItemCanceladoCellFactory implements Callback<TableColumn, TableCell> {
    @Override
    public TableCell call(TableColumn tableColumn) {
        return new TableCell<ItemBean, Object>() {
            @Override
            public void updateItem(Object item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty ? "" : getItem().toString());
                setGraphic(null);
                int indice=getIndex();
                ItemBean bean=null;
                if(indice<getTableView().getItems().size())
                    bean = getTableView().getItems().get(indice);
                if (bean != null && bean.isCancelado())
                    getStyleClass().add("itemCancelado");
            }
        };
    }
}

Здесь есть еще одна проблема: строка, помеченная как отмененная, меняет цвет только тогда, когда пользователь добавляет или удаляет элемент из наблюдаемого списка. Есть ли способ заставить обновление TableView?

РЕДАКЦИОННАЯ ИНФОРМАЦИЯ

Я изменил класс ItemBean для использования BooleanProperty, и он решил частично:

public class ItemBean {
    ...
    private BooleanProperty cancelado = new SimpleBooleanProperty(false);
    ...
    public Boolean getCancelado() {
        return cancelado.get();
    }

    public void setCancelado(Boolean cancelado){
        this.cancelado.set(cancelado);
    }

    public BooleanProperty canceladoProperty(){
        return cancelado;
    }
}

К сожалению, только столбец "отмена" (который будет скрыт или удален, когда это наконец сработает) изменяет внешний вид:

столбец отмена изменяет внешний вид

здесь я настраиваю столбцы и таблицу:

public class ControladorPainelPreVenda extends ControladorPainel {

    @FXML
    private TableView<ItemBean> tabelaItens;
    private ObservableList<ItemBean> itens = FXCollections.observableArrayList();
    ...

    private void configurarTabela() {
        colunaCodigo.setCellValueFactory(new MultiPropertyValueFactory<ItemBean, String>("produto.id"));
        colunaCodigo.setCellFactory(new ItemCanceladoCellFactory());
        colunaDescricao.setCellValueFactory(new MultiPropertyValueFactory<ItemBean, String>("produto.descricao"));
        colunaDescricao.setCellFactory(new ItemCanceladoCellFactory());
        colunaLinha.setCellValueFactory(new MultiPropertyValueFactory<ItemBean, String>("produto.nomeLinha"));
        colunaLinha.setCellFactory(new ItemCanceladoCellFactory());
        colunaQuantidade.setCellValueFactory(new PropertyValueFactory<ItemBean, BigDecimal>("quantidade"));
        colunaQuantidade.setCellFactory(new ItemCanceladoCellFactory());
        colunaValorLiquido.setCellValueFactory(new PropertyValueFactory<ItemBean, BigDecimal>("valorLiquido"));
        colunaValorLiquido.setCellFactory(new ItemCanceladoCellFactory());
        colunaValorTotal.setCellValueFactory(new PropertyValueFactory<ItemBean, BigDecimal>("valorTotal"));
        colunaValorTotal.setCellFactory(new ItemCanceladoCellFactory());
        colunaCancelado.setCellValueFactory(new PropertyValueFactory<ItemBean, Boolean>("cancelado"));
        colunaCancelado.setCellFactory(new ItemCanceladoCellFactory());
        tabelaItens.setItems(itens);
    }
    ...
}

Как я могу обновить все столбцы?

3 ответа

Решение

Есть ли способ заставить обновление TableView?

Сделать Cancelado свойство ItemBean учебный класс:

private BooleanProperty cancelado = new SimpleBooleanProperty(false);
public BooleanProperty canceladoProperty() { 
  return cancelado;
}

Теперь реализация ячейки по умолчанию для представления списка будет прослушивать изменения в cancelado свойство и триггер updateItem при необходимости вызывает соответствующую ячейку просмотра списка.

Обратите внимание, что имя функции, которая возвращает свойство, важно, оно должно быть canceladoProperty() поскольку JavaFX расширяет стандартную модель получения и установки элемента Java Beans для свойств.

Соглашение об именах собственности

Соглашение об именовании для доступа к свойствам JavaFX продемонстрировано в этом фрагменте кода из руководства Oracle " Использование свойств JavaFX и привязки".

package propertydemo;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

class Bill {

    // Define a variable to store the property
    private DoubleProperty amountDue = new SimpleDoubleProperty();

    // Define a getter for the property's value
    public final double getAmountDue(){return amountDue.get();}

    // Define a setter for the property's value
    public final void setAmountDue(double value){amountDue.set(value);}

     // Define a getter for the property itself
    public DoubleProperty amountDueProperty() {return amountDue;}

}

На вики-сайте openfx представлен большой обзор архитектуры свойств JavaFX, в котором подробно описаны соглашения об именах свойств и различные более сложные сценарии использования, такие как свойства только для чтения и свойства lazy.

Настройка внешнего вида строки в табличном представлении

Более подробная информация и пример настройки внешнего вида строки таблицы на основе логического значения строки представлены в этом основном примере кода.

private TableColumn<Friend, Boolean> makeBooleanColumn(String columnName, String propertyName, int prefWidth) {
  TableColumn<Friend, Boolean> column = new TableColumn<>(columnName);
  column.setCellValueFactory(new PropertyValueFactory<Friend, Boolean>(propertyName));
  column.setCellFactory(new Callback<TableColumn<Friend, Boolean>, TableCell<Friend, Boolean>>() {
    @Override public TableCell<Friend, Boolean> call(TableColumn<Friend, Boolean> soCalledFriendBooleanTableColumn) {
      return new TableCell<Friend, Boolean>() {
        @Override public void updateItem(final Boolean item, final boolean empty) {
          super.updateItem(item, empty);

          // clear any custom styles
          this.getStyleClass().remove("willPayCell");
          this.getStyleClass().remove("wontPayCell");
          this.getTableRow().getStyleClass().remove("willPayRow");
          this.getTableRow().getStyleClass().remove("wontPayRow");

          // update the item and set a custom style if necessary
          if (item != null) {
            setText(item.toString());
            this.getStyleClass().add(item ? "willPayCell" : "wontPayCell");
            this.getTableRow().getStyleClass().add(item ? "willPayRow" : "wontPayRow");
          }
        }
      };
    }
  });
  column.setPrefWidth(prefWidth);
}

связанные с

Вопрос Stackru Фон с 2 цветами в JavaFX?, предоставляет аналогичное решение. Обсуждение в ответе на этот вопрос предоставляет дополнительную информацию о предостережениях и тонкостях выделения строк таблицы в JavaFX (в основном, очень трудно получить стили псевдо-класса - кольца фокуса, выбранные полосы, обратную связь при наведении курсора и т. Д. - прямо с пользовательской строкой стили).

Вы должны установить зачеркнутый класс.text:;-)

.itemCancelado {
    -fx-text-fill: red;
}
.itemCancelado .text {
    -fx-strikethrough: true;
}

Как я могу обновить все столбцы? Если вы хотите вычеркнуть всю строку, т. Е. Все ячейки в строке, каждая другая CellValueFactory должна иметь проверку этого условия:

    ...
    if (indice < getTableView().getItems().size())
        bean = getTableView().getItems().get(indice);
    if (bean != null && bean.isCancelado())
        getStyleClass().add("itemCancelado");
    ...

Или вы можете реализовать свои обратные вызовы как декораторы и получить что-то вроде этого:

public class CellDecorator implements Callback<TableColumn, TableCell> {
    private Callback<TableColumn, TableCell> decorated;

    public CellDecorator(Callback<TableColumn, TableCell> toDecorate) {
      this.decorated = toDecorate;
    }

    // Override this to do your thing.
    public abstract void doStyle(TableCell tableCell);

    @Override
    public void style(TableCell tableCell) {
        // Let the decorated styler do its thing.
        decorated.style(tableCell);

        // Now we do our thing.
        doStyle(cell);
    }
}

public class ItemCanceladoCellFactory extends CellDecorator {
    public ItemCanceladoCellFactory(Callback<TableColumn, TableCell> toDecorate) {
      super(toDecorate);
    }

    @Override
    public void doStyle(TableCell tableCell) {
        ...
        if (bean != null && bean.isCancelado())
            getStyleClass().add("itemCancelado");
    }
}

...
colunaCodigo.setCellValueFactory(new ItemCanceladoCellFactory(new MultiPropertyValueFactory<ItemBean, String>("produto.id")));
colunaDescricao.setCellValueFactory(new ItemCanceladoCellFactory(new MultiPropertyValueFactory<ItemBean, String>("produto.descricao")));
colunaDescricao.setCellFactory(new ItemCanceladoCellFactory(new ItemCanceladoCellFactory()));
....

Таким образом, вам не нужно повторять "отмененный" код стиля, и вы можете применить его ко всей строке. Обратите внимание, что это не готовый код JavaFX, это общая идея.

Другие вопросы по тегам