13

我在更改某些 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);
    }
    ...
}

如何更新所有列?

4

3 回答 3

9

有没有办法强制更新 TableView?

创建类的Canceladoa 属性ItemBean

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

现在,列表视图的默认单元格实现将侦听cancelado属性的更改并适当地触发updateItem对相关列表视图单元格的调用。

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

属性命名约定背景

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 wiki 上对JavaFX 属性架构有一个很好的概述,其中详细介绍了属性的命名约定以及各种更高级的使用场景,例如只读属性和惰性属性。

在 TableView 中自定义行的外观

此gist 示例代码中提供了更多信息和基于布尔行值自定义表格行外观的示例。

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 中有 2 种颜色的背景?, 提供了类似的解决方案。该问题的答案中的讨论提供了有关 JavaFX 中表格行突出显示的警告和微妙之处的更多信息(基本上,很难获得伪类样式 - 焦点环、选定条、悬停反馈等 - 正确使用自定义行样式)。

于 2013-04-25T07:42:00.203 回答
5

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

.itemCancelado {
    -fx-text-fill: red;
}
.itemCancelado .text {
    -fx-strikethrough: true;
}
于 2013-04-25T07:22:44.710 回答
3

如何更新所有列? 如果您希望删除整行,即一行中的所有单元格,则每个其他 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 就绪的代码,这是一个普遍的想法。

于 2013-04-30T13:20:11.877 回答