JavaFX:将新行添加到 table 后更改单元格颜色
JavaFX: Change cell color after adding new row to the table
我有一个程序可以读取某些文件,然后在 table 中显示值。用户可以通过按钮添加新行。
现在我想更改添加行的背景颜色,以便用户可以看到新旧内容。
我现在的问题是,如何直接select新行然后改变背景颜色?
我知道如何使用 class TablePosition 获取单个单元格的位置。
例子
TablePosition pos = tableView.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
int col = pos.getColumn();
TableColumn column = pos.getTableColumn();
但是如果我想要整行,它是如何工作的呢?
预期结果
最后我希望我可以对添加的行进行 select 编辑,以便我可以更改背景颜色。
创建一个可以存储新项目的可观察集合。ObservableSet
做得很好。
进一步为 TableView
创建自定义 rowFactory
。每次项目或集合更改时,工厂创建的行都会更新样式。这使您可以非常轻松地修改所选项目。
示例:
@Override
public void start(Stage primaryStage) throws Exception {
// bad design here, but this type is not important
class Item {
final StringProperty value;
Item(String value) {
this.value = new SimpleStringProperty(value);
}
}
TableView<Item> table = new TableView();
TableColumn<Item, String> column = new TableColumn<>("value");
column.setCellValueFactory(i -> i.getValue().value);
table.getColumns().add(column);
for (int i = 0; i < 20; i++) {
table.getItems().add(new Item(Integer.toString(i)));
}
// set storing items to be marked as new
final ObservableSet<Item> newItems = FXCollections.observableSet(new HashSet<>());
final PseudoClass newPc = PseudoClass.getPseudoClass("new");
table.setRowFactory(t -> new TableRow<Item>() {
private final InvalidationListener l = o -> update();
// prevent memory leak for cells that are "thrown away"
private final WeakInvalidationListener listener = new WeakInvalidationListener(l);
{
newItems.addListener(listener);
}
private void update() {
pseudoClassStateChanged(newPc, isEmpty() || newItems.contains(getItem()));
}
@Override
protected void updateItem(Item item, boolean empty) {
super.updateItem(item, empty);
update();
}
});
// create buttons modifying the new items
Button addButton = new Button("add");
addButton.setOnAction(new EventHandler<ActionEvent>() {
int counter = 20;
@Override
public void handle(ActionEvent event) {
for (int i = 0; i < 3; i++, counter++) {
Item item = new Item(Integer.toString(counter));
newItems.add(item);
table.getItems().add(item);
}
}
});
Button clearNew = new Button("clear new");
clearNew.setOnAction(evt -> newItems.clear());
Scene scene = new Scene(new HBox(table, new VBox(addButton, clearNew)));
scene.getStylesheets().add(getClass().getResource("/path/to/my/style.css").toString());
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.table-row-cell:new {
-fx-background: #DDDD00;
}
.table-row-cell:new:selected {
-fx-background: #BBBB00;
}
我有一个程序可以读取某些文件,然后在 table 中显示值。用户可以通过按钮添加新行。
现在我想更改添加行的背景颜色,以便用户可以看到新旧内容。
我现在的问题是,如何直接select新行然后改变背景颜色?
我知道如何使用 class TablePosition 获取单个单元格的位置。
例子
TablePosition pos = tableView.getSelectionModel().getSelectedCells().get(0);
int row = pos.getRow();
int col = pos.getColumn();
TableColumn column = pos.getTableColumn();
但是如果我想要整行,它是如何工作的呢?
预期结果
最后我希望我可以对添加的行进行 select 编辑,以便我可以更改背景颜色。
创建一个可以存储新项目的可观察集合。ObservableSet
做得很好。
进一步为 TableView
创建自定义 rowFactory
。每次项目或集合更改时,工厂创建的行都会更新样式。这使您可以非常轻松地修改所选项目。
示例:
@Override
public void start(Stage primaryStage) throws Exception {
// bad design here, but this type is not important
class Item {
final StringProperty value;
Item(String value) {
this.value = new SimpleStringProperty(value);
}
}
TableView<Item> table = new TableView();
TableColumn<Item, String> column = new TableColumn<>("value");
column.setCellValueFactory(i -> i.getValue().value);
table.getColumns().add(column);
for (int i = 0; i < 20; i++) {
table.getItems().add(new Item(Integer.toString(i)));
}
// set storing items to be marked as new
final ObservableSet<Item> newItems = FXCollections.observableSet(new HashSet<>());
final PseudoClass newPc = PseudoClass.getPseudoClass("new");
table.setRowFactory(t -> new TableRow<Item>() {
private final InvalidationListener l = o -> update();
// prevent memory leak for cells that are "thrown away"
private final WeakInvalidationListener listener = new WeakInvalidationListener(l);
{
newItems.addListener(listener);
}
private void update() {
pseudoClassStateChanged(newPc, isEmpty() || newItems.contains(getItem()));
}
@Override
protected void updateItem(Item item, boolean empty) {
super.updateItem(item, empty);
update();
}
});
// create buttons modifying the new items
Button addButton = new Button("add");
addButton.setOnAction(new EventHandler<ActionEvent>() {
int counter = 20;
@Override
public void handle(ActionEvent event) {
for (int i = 0; i < 3; i++, counter++) {
Item item = new Item(Integer.toString(counter));
newItems.add(item);
table.getItems().add(item);
}
}
});
Button clearNew = new Button("clear new");
clearNew.setOnAction(evt -> newItems.clear());
Scene scene = new Scene(new HBox(table, new VBox(addButton, clearNew)));
scene.getStylesheets().add(getClass().getResource("/path/to/my/style.css").toString());
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.table-row-cell:new {
-fx-background: #DDDD00;
}
.table-row-cell:new:selected {
-fx-background: #BBBB00;
}