JavaFX TableView单元格颜色更改取决于文本值

时间:2017-09-08 09:30:10

标签: javafx tableview cell background-color

我有一个带有TableView的JavaFX桌面应用程序。我使用名为Orders的POJO填充数据,这些订单最终来自Firebird SQL数据库。 Image of what I have now

我要做的是更改第一列中每个单元格的背景填充颜色'状态'取决于文本值。因此,如果文本值是“准备好”,那么绿色,开始'将是黄色的' DONE'将是灰色的。 Image of what I would like

以下是我用来填充TableView的代码部分:

`
@FXML private TableView<Orders> tblOrders;
@FXML private TableColumn<Orders, Integer> clmStatus;
@FXML private TableColumn<Orders, String> clmStartDateTime;
@FXML private TableColumn<Orders, String> clmShopOrder;
@FXML private TableColumn<Orders, String> clmRotation;
@FXML private TableColumn<Orders, String> clmGMIECode;
@FXML private TableColumn<Orders, String> clmSAPCode;
@FXML private TableColumn<Orders, Integer> clmLineName;
@FXML private TableColumn<Orders, Integer> clmOrderProductionNr;
private ObservableList<Orders> list;

public void initialize(URL location, ResourceBundle resources) {
    populateTable();
}

private void populateTable() {
    log.appLog("Populating table\r\n");
    clmStatus.setCellValueFactory(new PropertyValueFactory<>("status"));
    clmStartDateTime.setCellValueFactory(new PropertyValueFactory<>
        ("startDateTime"));
    clmShopOrder.setCellValueFactory(new PropertyValueFactory<>("extra1"));
    clmRotation.setCellValueFactory(new 
        PropertyValueFactory<("batchLotNr"));
    clmGMIECode.setCellValueFactory(new PropertyValueFactory<>("wareNr"));
    clmSAPCode.setCellValueFactory(new PropertyValueFactory<>
        ("serviceDescription"));
    clmLineName.setCellValueFactory(new PropertyValueFactory<>
        ("productionLineNr"));
    clmOrderProductionNr.setCellValueFactory(new PropertyValueFactory<>
        ("orderProductionNr"));
    tblOrders.setItems(list);
}
`

我的订单POJO的代码示例:

`
public class Orders {
    private final SimpleStringProperty status;
    private final SimpleStringProperty startDateTime;
    private final SimpleStringProperty extra1;
    private final SimpleStringProperty batchLotNr;
    private final SimpleStringProperty wareNr;
    private final SimpleStringProperty serviceDescription;
    private final SimpleStringProperty productionLineNr;
    private final SimpleIntegerProperty orderProductionNr;

    Orders(String status, String startDateTime, String extra1, String batchLotNr, String wareNr, String serviceDescription, String productionLineNr, int orderProductionNr) {
        this.status = new SimpleStringProperty(status);
        this.startDateTime = new SimpleStringProperty(startDateTime);
        this.extra1 = new SimpleStringProperty(extra1);
        this.batchLotNr = new SimpleStringProperty(batchLotNr);
        this.wareNr = new SimpleStringProperty(wareNr);
        this.serviceDescription = new SimpleStringProperty(serviceDescription);
        this.productionLineNr = new SimpleStringProperty(productionLineNr);
        this.orderProductionNr = new SimpleIntegerProperty((orderProductionNr));
    }

    public String getStatus() {
        return status.get();
    }

    public String getStartDateTime() {return startDateTime.get(); }

    public String getExtra1() {
        return extra1.get();
    }

    public String getBatchLotNr() {
        return batchLotNr.get();
    }

    public String getWareNr() {
        return wareNr.get();
    }

    public String getServiceDescription() {
        return serviceDescription.get();
    }

    public String getProductionLineNr() {
        return productionLineNr.get();
    }

    int getOrderProductionNr() {return orderProductionNr.get();}
}
`

我尝试过使用回调但我以前从未使用过回调,也没有正确理解我如何能够满足回调需求。任何帮助对我的学习都很重要。谢谢你。

2 个答案:

答案 0 :(得分:2)

我终于找到了解决方案而无需使用任何额外的类,只需在我的控制器类中通过此SO链接进行回调: StackOverFlow Link

`
private void populateTable() {
        log.appLog("Populating table\r\n");
        //clmStatus.setCellValueFactory(new PropertyValueFactory<>("status"));

        clmStatus.setCellFactory(new Callback<TableColumn<Orders, String>,
                TableCell<Orders, String>>()
        {
            @Override
            public TableCell<Orders, String> call(
                    TableColumn<Orders, String> param) {
                return new TableCell<Orders, String>() {
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        if (!empty) {
                            int currentIndex = indexProperty()
                                    .getValue() < 0 ? 0
                                    : indexProperty().getValue();
                            String clmStatus = param
                                    .getTableView().getItems()
                                    .get(currentIndex).getStatus();
                            if (clmStatus.equals("READY")) {
                                setTextFill(Color.WHITE);
                                setStyle("-fx-font-weight: bold");
                                setStyle("-fx-background-color: green");
                                setText(clmStatus);
                            } else if (clmStatus.equals("STARTED")){
                                setTextFill(Color.BLACK);
                                setStyle("-fx-font-weight: bold");
                                setStyle("-fx-background-color: yellow");
                                setText(clmStatus);
                            } else if (clmStatus.equals("DONE")){
                                setTextFill(Color.BLACK);
                                setStyle("-fx-font-weight: bold");
                                setStyle("-fx-background-color: gray");
                                setText(clmStatus);
                            } else {
                                setTextFill(Color.WHITE);
                                setStyle("-fx-font-weight: bold");
                                setStyle("-fx-background-color: red");
                                setText(clmStatus);
                            }
                        }
                    }
                };
            }
        });

        clmStartDateTime.setCellValueFactory(new PropertyValueFactory<>("startDateTime"));
        clmShopOrder.setCellValueFactory(new PropertyValueFactory<>("extra1"));
        clmRotation.setCellValueFactory(new PropertyValueFactory<>("batchLotNr"));
        clmGMIECode.setCellValueFactory(new PropertyValueFactory<>("wareNr"));
        clmSAPCode.setCellValueFactory(new PropertyValueFactory<>("serviceDescription"));
        clmLineName.setCellValueFactory(new PropertyValueFactory<>("productionLineNr"));
        clmOrderProductionNr.setCellValueFactory(new PropertyValueFactory<>("orderProductionNr"));
        tblOrders.setItems(list);
    }
`

答案 1 :(得分:0)

您必须为状态列定义自定义TableCell,如下所示:

public class ColoredStatusTableCell extends TableCell<TableRow, Status> {

    @Override
    protected void updateItem(Status item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || getTableRow() == null) {
            setText(null);
            setGraphic(null);
        } else {
            TableRow row = (TableRow) getTableRow().getItem();
            setText(item.toString());
            setStyle("-fx-background-color: " + row.getColorAsString());
            // If the statis is changing dynamic you have to add the following:
            row.statusProperty()
                .addListener((observable, oldValue, newValue) -> 
                        setStyle("-fx-background-color: " + row.getColorAsString()));
        }
    }
}

TableRow

public class TableRow {

    private ObjectProperty<Status> status;
    private Map<Status, Color> statusColor;

    public TableRow(Status status, Map<Status, Color> statusColor) {
        this.status = new SimpleObjectProperty<>(status);
        this.statusColor = statusColor;
    }

    public Status getStatus() {
        return status.get();
    }

    public ObjectProperty<Status> statusProperty() {
        return status;
    }

    public Color getStatusColor() {
        return statusColor.get(status.get());
    }

    public String getColorAsString() {
        return String.format("#%02X%02X%02X",
                (int) (getStatusColor().getRed() * 255),
                (int) (getStatusColor().getGreen() * 255),
                (int) (getStatusColor().getBlue() * 255));
    }
}

状态:

public enum Status {
    READY, STARTED, DONE
}

和控制器:

public class TestController {

    @FXML
    private TableView<TableRow> table;
    @FXML
    private TableColumn<TableRow, Status> column;

    private ObservableList<TableRow> data = FXCollections.observableArrayList();

    @FXML
    public void initialize() {
        column.setCellValueFactory(data -> data.getValue().statusProperty());
        column.setCellFactory(factory -> new ColoredStatusTableCell());
        Map<Status, Color> statusColor = new HashMap<>();
        statusColor.put(Status.READY, Color.GREEN);
        statusColor.put(Status.STARTED, Color.YELLOW);
        statusColor.put(Status.DONE, Color.GRAY);

        TableRow ready = new TableRow(Status.READY, statusColor);
        TableRow started = new TableRow(Status.STARTED, statusColor);
        TableRow done = new TableRow(Status.DONE, statusColor);

        data.addAll(ready, started, done);

        table.setItems(data);
    }

}

我选择将状态设置为enum,因为它更容易处理, 然后我使用了一个地图到每个状态 - 颜色组合,然后在单元格中,您可以将其背景颜色设置为状态的匹配颜色。

如果你想要而不是Color.YELLOW等,你可以使用自定义Color.rgb(red,green,blue)