JavaFX - 如何使用 Java-代码更改选定 TableColumn 的颜色?

JavaFX - How to change the color of a selected TableColumn with Java-Code?

我有一个简单的 TableView,它有两列(Id,Valid)。
table 的代码如下所示:

private TableView<List<Object>> createTable()
    {
       TableView<List<Object>> table = new TableView<>();

       TableColumn<List<Object>, String> idCol = new TableColumn<>("ID");
       idCol.setCellValueFactory(new Callback<CellDataFeatures<List<Object>, String>, ObservableValue<String>>()
       {
          public ObservableValue<String> call(CellDataFeatures<List<Object>, String> param)
          {
             return new SimpleStringProperty(param.getValue().get(0).toString());
          }
       });
       TableColumn<List<Object>, String> validCol = new TableColumn<>("Valid");
       validCol.setCellValueFactory(new Callback<CellDataFeatures<List<Object>, String>, ObservableValue<String>>()
       {
          public ObservableValue<String> call(CellDataFeatures<List<Object>, String> param)
          {
             return new SimpleStringProperty(param.getValue().get(1).toString());
          }
       });
       table.getColumns().addAll(idCol, validCol);

       List<Object> firstRow = new ArrayList<Object>();
       firstRow.add(1);
       firstRow.add(0);
       List<Object> secondRow = new ArrayList<Object>();
       secondRow.add(2);
       secondRow.add(1);
       table.getItems().addAll(firstRow, secondRow);

       return table;
    }

有效行的背景应变为绿色,无效行的背景应变为红色。我意识到通过设置一个 rowfactory:

table.setRowFactory(new Callback<TableView<List<Object>>, TableRow<List<Object>>>()
   {
      @Override
      public TableRow<List<Object>> call(TableView<List<Object>> param)
      {
         return new TableRow<List<Object>>()
         {
            @Override
            protected void updateItem(List<Object> item, boolean empty)
            {
                super.updateItem(item, empty);
                if (!empty)
                {
                   int valid = Integer.parseInt(item.get(1).toString());
                   if (valid == 1)
                      setBackground(MyCustomBackGround.VALID);
                   else if (valid == 0)
                      setBackground(MyCustomBackGround.NOT_VALID);
                   else
                      setBackground(MyCustomBackGround.WHITE);
                }
            }
         };
      }
   });

这似乎工作正常。但现在我想改变我选择的颜色。可以说我想使设置的颜色变暗。
我怎样才能意识到这一点?

您可以像下面这样使用 Bindings。或者你可以使用 CSSPseudoClasses.

table.setRowFactory(tv -> new TableRow<>() {
    private final Background
            validBackground = new Background(new BackgroundFill(Color.LIGHTGREEN, CornerRadii.EMPTY, Insets.EMPTY)),
            validSelectedBackground = new Background(new BackgroundFill(Color.DARKGREEN, CornerRadii.EMPTY, Insets.EMPTY)),
            invalidBackground = new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)),
            invalidSelectedBackground = new Background(new BackgroundFill(Color.DARKRED, CornerRadii.EMPTY, Insets.EMPTY));

    @Override
    public void updateItem(Item item, boolean empty) {
        super.updateItem(item, empty);

        if (item == null || empty)
            backgroundProperty().unbind();
        else
            backgroundProperty().bind(Bindings.when(item.validProperty())
                    .then(Bindings.when(selectedProperty())
                            .then(validSelectedBackground)
                            .otherwise(validBackground))
                    .otherwise(Bindings.when(selectedProperty())
                            .then(invalidSelectedBackground)
                            .otherwise(invalidBackground)));
    }
});

更新:示例 css.

App.java:

package org.example;

import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

import java.util.Objects;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class App extends Application {

    @Override
    public void start(Stage stage) {

        // Create table with columns:
        TableView<Item> table = new TableView<>();

        TableColumn<Item, Integer> idCol = new TableColumn<>("ID");
        TableColumn<Item, Boolean> validCol = new TableColumn<>("Valid");

        Stream.of(idCol, validCol).forEach(col -> table.getColumns().add(col));

        idCol.setCellValueFactory(cellData -> cellData.getValue().idProperty().asObject());
        validCol.setCellValueFactory(cellData -> cellData.getValue().validProperty());

        // Create pseudo classes:
        PseudoClass validPseudoClass = PseudoClass.getPseudoClass("valid"),
                invalidPseudoClass = PseudoClass.getPseudoClass("invalid");

        // Customized row factory:
        table.setRowFactory(tv -> {
            TableRow<Item> row =  new TableRow<>();
            row.itemProperty().addListener((observable, oldValue, newValue) -> {
                if (newValue != null) {
                    row.pseudoClassStateChanged(validPseudoClass, newValue.isValid());
                    row.pseudoClassStateChanged(invalidPseudoClass, !newValue.isValid());
                } else {
                    row.pseudoClassStateChanged(validPseudoClass, false);
                    row.pseudoClassStateChanged(invalidPseudoClass, false);
                }
                table.refresh();
            });
            return row ;
        });

        // Create test data:
        IntStream.range(0, 5).forEach(i -> table.getItems().add(new Item(i, true)));
        IntStream.of(1, 3).forEach(i -> table.getItems().get(i).setValid(false));

        // Prepare and show scene:
        Scene scene = new Scene(new Pane(table));
        scene.getStylesheets().add(Objects.requireNonNull( // Load the css file
                App.class.getResource("styling.css")).toExternalForm()); 
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

styling.css:

.table-row-cell:valid {
    -fx-background: green;
}

.table-row-cell:valid:selected {
    -fx-background: darkgreen;
}

.table-row-cell:invalid {
    -fx-background: red;
}

.table-row-cell:invalid:selected {
    -fx-background: darkred;
}

我的解决方案

我像@anko 回答的那样做了,因为我没有数据模型对象。我使用了伪类和拟合 css.

表格视图

public TableView<List<Object>> getTableView()
{
   TableView<List<Object>> table = new TableView<List<Object>>();
   table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
   fillTableWithData();
   table.setColumnResizePolicy(STFTableView.CONSTRAINED_RESIZE_POLICY);

   // Create pseudo classes to be available in CSS:
   PseudoClass validPseudoClass = PseudoClass.getPseudoClass("valid"),
         invalidPseudoClass = PseudoClass.getPseudoClass("invalid");

   // Customized row factory:
   table.setRowFactory(tv ->
      {
         int validIdx = /*calculated*/;
         TableRow<List<Object>> row = new TableRow<>();
         row.itemProperty().addListener((observable, oldValue, newValue) ->
            {
                if (newValue != null && newValue.get(validIdx) != null)
                {
                   row.pseudoClassStateChanged(validPseudoClass, newValue.get(validIdx).equals(1));
                   row.pseudoClassStateChanged(invalidPseudoClass, newValue.get(validIdx).equals(0));
                }
                else
                {
                   row.pseudoClassStateChanged(validPseudoClass, false);
                   row.pseudoClassStateChanged(invalidPseudoClass, false);
                }
                table.refresh();
            });
         return row;
      });
   return table;
}

styling.css


.table-row-cell:valid {
    -fx-background: white
}

.table-row-cell:valid:selected {
    -fx-background: gray
}

.table-row-cell:invalid {
    -fx-background: red;
}

.table-row-cell:invalid:selected {
    -fx-background: darkred;
}