我需要在具有可变列数的TableView中更改任意单元格的样式。下面的代码显示了基本问题。
ExampleRow类是来自电子表格的真实数据的代理,其他功能是保存突出显示信息。由于我不知道会有多少列,所以我只保留一列应该突出显示的列(不支持列重新排列)。 ExampleTableCell类只设置单元格的文本,并在需要时应用突出显示。
如果我在绘制表格[cell(2,2)]之前设置了一个突出显示,那么当应用程序启动时,单元格会正确显示红色文本。问题是单击按钮设置单元格(1,1)以突出显示但表格不会更改。如果我将应用程序窗口的大小调整为空,则再次打开它,正确绘制单元格(1,1)的突出显示 - 大概是因为此过程强制完全重绘。
我想知道的是如何触发表重新绘制新突出显示的单元格(或所有可见单元格),以便样式正确?
TIA
package example;
import java.util.HashSet;
import java.util.Set;
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class CellHighlightExample extends Application {
private final int columnCount = 4;
private final int rowCount = 5;
private TableView<ExampleRow> table = new TableView<>();
@Override
public void start(Stage stage) {
BorderPane root = new BorderPane();
Scene scene = new Scene(root);
Callback<TableColumn.CellDataFeatures<ExampleRow, String>, ObservableValue<String>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ExampleRow, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<ExampleRow, String> p) {
int row = p.getValue().getRow();
int col = p.getTableView().getColumns().indexOf(p.getTableColumn());
return new SimpleObjectProperty<>("(" + row + ", " + col + ")");
}
};
Callback<TableColumn<ExampleRow, String>, TableCell<ExampleRow, String>> cellFactory = new Callback<TableColumn<ExampleRow, String>, TableCell<ExampleRow, String>>() {
@Override
public TableCell<ExampleRow, String> call(TableColumn<ExampleRow, String> p) {
return new ExampleTableCell<>();
}
};
for (int i = 0, n = columnCount; i < n; i++) {
TableColumn<ExampleRow, String> column = new TableColumn<>();
column.setCellValueFactory(cellValueFactory);
column.setCellFactory(cellFactory);
table.getColumns().add(column);
}
ObservableList<ExampleRow> rows = FXCollections.observableArrayList();
for (int i = 0, n = rowCount; i < n; i++) {
ExampleRow row = new ExampleRow(i);
//Force a cell to be highlighted to show that highlighting works.
if (i == 2) { row.addHighlightedColumn(2); }
rows.add(row);
}
table.setItems(rows);
Button b = new Button("Click to Highlight");
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
ExampleRow row = table.getItems().get(1);
row.addHighlightedColumn(1);
//How to trigger a redraw of the table or cell to reflect the new highlighting?
}
});
root.setTop(b);
root.setCenter(table);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private class ExampleTableCell<S extends ExampleRow, T extends String> extends TableCell<S, T> {
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setText(null);
setGraphic(null);
} else {
setText(item);
int colIndex = getTableView().getColumns().indexOf(getTableColumn());
ExampleRow row = getTableView().getItems().get(getIndex());
if (row.isHighlighted(colIndex)) {
setTextFill(Color.RED);
}
}
}
}
private class ExampleRow {
private SimpleIntegerProperty row;
private Set<Integer> highlightedColumns = new HashSet<>();
public ExampleRow(int row) {
this.row = new SimpleIntegerProperty(row);
}
public int getRow() { return row.get(); }
public void setRow(int row) { this.row.set(row); }
public SimpleIntegerProperty rowProperty() { return row; }
public boolean isHighlighted(int col) {
if (highlightedColumns.contains(col)) {
return true;
}
return false;
}
public void addHighlightedColumn(int col) {
highlightedColumns.add(col);
}
}
}
答案 0 :(得分:6)
关于这个问题有很多讨论,即在改变项目后刷新tableview
见
JavaFX 2.1 TableView refresh items
问题
http://javafx-jira.kenai.com/browse/RT-21822
http://javafx-jira.kenai.com/browse/RT-22463
http://javafx-jira.kenai.com/browse/RT-22599
解决方案是触发内部tableview更新方法。有人建议删除tableview项并再次添加它们..但对你的案例最简单的解决方法似乎是:
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
ExampleRow row = table.getItems().get(1);
row.addHighlightedColumn(1);
//How to trigger a redraw of the table or cell to reflect the new highlighting?
// Workaround
table.getColumns().get(0).setVisible(false);
table.getColumns().get(0).setVisible(true);
}
});
在上面链接的问题评论中找到。这是一个真正的解决方法或错觉吗?你需要自己深入挖掘。