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
。或者你可以使用 CSS
和 PseudoClasses
.
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;
}
我有一个简单的 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
。或者你可以使用 CSS
和 PseudoClasses
.
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;
}