Актуализиране на вида на реда на 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" (която ще бъде скрита или премахната, когато това най-накрая работи) променя външния вид:

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

}

Има страхотен преглед на JavaFX Property Architecture в wiki на openfx който подробно описва конвенциите за именуване на свойства и различни по-усъвършенствани сценарии на използване като свойства само за четене и мързеливи свойства.

Персонализиране на външния вид на ред в 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 Фон с 2 цвята в JavaFX? предоставя подобно решение. Дискусията в отговора на този въпрос предоставя допълнителна информация относно предупрежденията и тънкостите на осветяването на редовете на таблицата в JavaFX (по принцип е наистина трудно да се получат псевдокласовите стилове - пръстени за фокусиране, избрани ленти, обратна връзка при задържане и т.н. - точно с персонализиран ред стилове).

person jewelsea    schedule 25.04.2013
comment
Трябва да посочите метода, който извлича свойството cancelado canceladoProperty() както в моя пример, а не getCancelado() както в добавената информация във вашия въпрос. - person jewelsea; 26.04.2013
comment
Актуализиран отговор, за да покаже как можете да стилизирате цял ред, а не само клетка. - person jewelsea; 27.04.2013
comment
Все пак просто актуализирайте колоната cancelado. Мисля, че само колоната cellFactory на cancelado следи за промени... - person brevleq; 29.04.2013
comment
Една клетка cellFactory може да промени стила на целия ред, а не само на клетката, както е показано в примера за персонализиране на външния вид на ред в TableView, който публикувах в моя отговор. - 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