更新TableView行外观

时间:2013-04-22 18:11:29

标签: java javafx-2 javafx 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 column changes the appearance

这里我配置了列和表:

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 个答案:

答案 0 :(得分:9)

有没有办法可以强制更新TableView?

使Cancelado类的ItemBean属性:

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

现在,列表视图的默认单元格实现将侦听cancelado属性的更改,并根据需要触发相关列表视图单元格的updateItem调用。

请注意,返回属性的函数的名称很重要,它必须是canceladoProperty(),因为JavaFX扩展了标准Java Beans成员getter和属性的setter模式。

属性命名约定背景

Oracle Using JavaFX Properties and Binding教程的代码片段中演示了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 wiki上的JavaFX Property Architecture概述了详细的属性命名约定和各种更高级的使用场景,如只读属性和延迟属性。

在TableView中自定义行的外观

gist sample code中提供了更多信息以及基于布尔行值自定义表行外观的示例。

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问题Background with 2 colors in JavaFX?提供了类似的解决方案。在这个问题的答案中的讨论提供了关于JavaFX中表格突出显示的警告和细微之处的更多信息(基本上,很难获得伪造的样式 - 聚焦环,选定的条形图,悬停反馈等 - 正确的自定义行样式)。

答案 1 :(得分:5)

您必须将删除线设置为.text类:; - )

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

答案 2 :(得分:3)

如何更新所有列? 如果你希望删除整行,即连续的所有单元格,那么每隔一个CellValueFactory应该检查一下:

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

或者您可以将回调实现为decorators并具有以下内容:

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准备好的代码,这是一个大致的想法。