Обновление внешнего вида строки 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;
    }
}

К сожалению, только колонка «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);
    }
    ...
}

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


person brevleq    schedule 22.04.2013    source источник


Ответы (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. в котором подробно описаны соглашения об именах для свойств и различные более сложные сценарии использования, такие как свойства только для чтения и отложенные свойства.

Настройка внешнего вида строки в TableView

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

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);
}

Связанные

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

person jewelsea    schedule 25.04.2013
comment
Вы должны назвать метод, который извлекает свойство cancelado canceladoProperty(), как в моем примере, а не getCancelado(), как в добавленной информации в вашем вопросе. - person jewelsea; 26.04.2013
comment
Обновленный ответ, чтобы показать, как вы можете стилизовать всю строку, а не только ячейку. - person jewelsea; 27.04.2013
comment
Просто обновите столбец отмены. Я думаю, что только столбец cellFactory из столбца отмены прослушивает изменения... - person brevleq; 29.04.2013
comment
Одна фабрика ячеек может изменить стиль всей строки, а не только ячейки, как показано в примере «Настройка внешнего вида строки в табличном представлении», который я опубликовал в своем ответе. - person jewelsea; 29.04.2013

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

.itemCancelado {
    -fx-text-fill: red;
}
.itemCancelado .text {
    -fx-strikethrough: true;
}
person Kalaschni    schedule 25.04.2013
comment
Решил проблему страйка, но у меня все еще есть проблемы с обновлением TableView - person brevleq; 25.04.2013

Как обновить все столбцы? Если вы хотите зачеркнуть всю строку, то есть все ячейки в строке, каждая вторая 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, это общая идея.

person Cebence    schedule 30.04.2013