我有一个Tableview<ObservableList<Item>>
,在更新基础数据时没有更新。通过调试,我知道基础ObservableList<Item>>
正在正确更新。我确保所有Item
的属性都可见,格式为myFieldProperty()
。
这是我创建的表格:
pattern= new TableView<>(mainApp.getItemList());
for (ObservableList<Item> row : pattern.getItems()) {
for (int i= pattern.getColumns().size(); i<row.size(); i++){
final int columnIndex = i ;
TableColumn<ObservableList<Item>, Color> column = new TableColumn<>();
column.setCellValueFactory( rowData ->
rowData.getValue()
.get(columnIndex).displayColorProperty()); // the Item for this cell
column.setCellFactory(col -> {
ItemCell cell = new ItemCell();
cell.setOnMouseEntered( e -> {
if (cell.getItem() != null) {
@SuppressWarnings("unchecked")
ObservableList<Item> stitchRow =
(ObservableList<Item>) cell.getTableRow().getItem();
mainApp.getRLController().setItemLabel(itemRow.get(columnIndex).toString());
}
});
cell.setOnMouseExited( e -> {
mainApp.getRLController().setItemLabel(null);
});
cell.setOnMouseClicked((MouseEvent e) -> {
Item newItem = mainApp.getTBController().getSelectedItem();
if (e.getButton() == MouseButton.PRIMARY && newItem != null) {
ObservableList<Item> itemRow =
(ObservableList<Item>) cell.getTableRow().getItem();
itemRow.set(columnIndex, newItem);
mainApp.getRLController().setItemLabel(itemRow.get(columnIndex).toString());
}
});
return cell;
});
column.setMinWidth(7);
column.setPrefWidth(7);
column.setMaxWidth(7);
pattern.getColumns().add(column);
}
}
pattern.setFixedCellSize(7);
pattern.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);`
我的自定义单元工厂的代码:
public class ItemCell extends TableCell<ObservableList<Item>, Color> {
@Override
protected void updateItem(Color color, boolean empty) {
super.updateItem(color, empty);
if (empty || color == null) {
setText(null);
setStyle(null);
} else {
int r = (int) (color.getRed() * 255);
int g = (int) (color.getGreen() * 255);
int b = (int) (color.getBlue() * 255);
this.setStyle("-fx-background-color: rgb(" + r + "," + g + "," + b + ");"
+ "-fx-border-color: black; -fx-table-cell-border-color: black;");
}
}
}
答案 0 :(得分:0)
基本问题是您要更改的对象(表示该行的列表元素的项目)不是单元格观察到更改的属性(属于该项目的displayColorProperty()
) 。您需要安排更改单元格正在观察的属性的值。
三种可能的解决方案:
如果可能,只需更改单元格显示的项目的displayColor
(以及其他数据)。即
cell.setOnMouseClicked((MouseEvent e) -> {
if (e.getButton() == MouseButton.PRIMARY && newItem != null) {
ObservableList<Item> itemRow =
(ObservableList<Item>) cell.getTableRow().getItem();
Item item = itemRow.get(columnIndex);
item.setDisplayColor(...);
item.set...(...);
// ...
mainApp.getRLController().setItemLabel(item.toString());
}
});
或者,替换整行:
cell.setOnMouseClicked((MouseEvent e) -> {
Item newItem = mainApp.getTBController().getSelectedItem();
if (e.getButton() == MouseButton.PRIMARY && newItem != null) {
ObservableList<Item> itemRow =
(ObservableList<Item>) cell.getTableRow().getItem();
ObservableList<Item> newRow = FXCollections.observableArrayList(itemRow);
newRow.set(columnIndex, newItem);
pattern.getItems().set(cell.getTableRow().getIndex(), newRow);
mainApp.getRLController().setItemLabel(newRow.get(columnIndex).toString());
}
});
否则,您可以将表格设为TableView<ObservableList<ObjectProperty<Item>>>
。这有点棘手,但不是太糟糕。这样,您只需将对象属性的值设置为新项即可。
以下是使用第三种技术的完整示例:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
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;
public class ColorTableExample extends Application {
@Override
public void start(Stage primaryStage) {
TableView<ObservableList<ObjectProperty<Item>>> table = new TableView<>();
int NUM_ROWS = 20 ;
int NUM_COLS = 15 ;
ObservableList<ObservableList<ObjectProperty<Item>>> data = table.getItems() ;
for (int y = 0 ; y < NUM_ROWS; y++) {
ObservableList<ObjectProperty<Item>> row = FXCollections.observableArrayList();
data.add(row);
double saturation = (1.0 * y) / NUM_ROWS ;
for (int x = 0 ; x < NUM_COLS; x++) {
double hue = x * 360.0 / NUM_COLS ;
Color color = Color.hsb(hue, saturation, 1.0);
row.add(new SimpleObjectProperty<>(new Item(color)));
}
}
for (ObservableList<ObjectProperty<Item>> row : table.getItems()) {
for (int i = table.getColumns().size() ; i < row.size(); i++) {
int columnIndex = i ;
TableColumn<ObservableList<ObjectProperty<Item>>, Item> column = new TableColumn<>(Integer.toString(i+1));
column.setCellValueFactory(rowData -> rowData.getValue().get(columnIndex));
column.setCellFactory(c -> {
TableCell<ObservableList<ObjectProperty<Item>>, Item> cell = new TableCell<ObservableList<ObjectProperty<Item>>, Item>() {
@Override
public void updateItem(Item item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setStyle("");
} else {
Color color = item.getDisplayColor() ;
int r = (int) (color.getRed() * 255) ;
int g = (int) (color.getGreen() * 255) ;
int b = (int) (color.getBlue() * 255) ;
String style = String.format(
"-fx-background-color: rgb(%d, %d, %d);"
+ "-fx-border-color: black ;"
+ "-fx-table-cell-border-color: black ;"
,r, g, b);
setStyle(style);
}
}
};
cell.setOnMousePressed(evt -> {
if (! cell.isEmpty()) {
ObservableList<ObjectProperty<Item>> rowData = (ObservableList<ObjectProperty<Item>>) cell.getTableRow().getItem();
Color currentColor = cell.getItem().getDisplayColor();
double newHue = ( currentColor.getHue() + 15 ) % 360 ;
Color newColor = Color.hsb(newHue, currentColor.getSaturation(), currentColor.getBrightness());
rowData.get(columnIndex).set(new Item(newColor));
}
});
return cell ;
});
table.getColumns().add(column);
}
}
BorderPane root = new BorderPane(table, null, null, null, null);
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
public static class Item {
private final ObjectProperty<Color> displayColor = new SimpleObjectProperty<>() ;
public Item(Color color) {
this.displayColorProperty().set(color);
}
public final ObjectProperty<Color> displayColorProperty() {
return this.displayColor;
}
public final javafx.scene.paint.Color getDisplayColor() {
return this.displayColorProperty().get();
}
public final void setDisplayColor(final javafx.scene.paint.Color displayColor) {
this.displayColorProperty().set(displayColor);
}
}
public static void main(String[] args) {
launch(args);
}
}
(在某些时候,重构一切可能更容易,因此你有一个实际的类代表表中的每一行,而不是使用列表。)
可能还有一个聪明的解决方法,使用提取器列表,但我无法做到这一点。