我的申请表中有TableView
。其中两列是付款日期和到期日。在每一行中,我想根据同一行中付款日期单元格的值更改各个到期日期单元格的背景颜色。我最好的尝试就在这里:
public class App extends Application {
private final TableView<Bill> tableView = new TableView<>();
private final TableColumn<Bill, Date> tableColumnExpirationDate;
private final TableColumn<Bill, Date> tableColumnPaymentDate;
public App() {
...
this.tableColumnExpirationDate = new TableColumn<>("Expires");
this.tableColumnPaymentDate = new TableColumn<>("Paid");
Callback<TableColumn<Bill, Date>, TableCell<Bill, Date>>
defaultTextFieldCellFactory =
TextFieldTableCell.<Bill, Date>forTableColumn(
new DateStringConverter());
tableColumnExpirationDate.setCellFactory(col -> {
TableCell<Bill, Date> cell = defaultTextFieldCellFactory.call(col);
Bill bill = tableView.getItems().get(cell.getIndex());
System.out.println("Bill: " + bill);
cell.setStyle("-fx-background-color: red;");
return cell;
});
tableColumnExpirationDate.setOnEditCommit(
new EventHandler<CellEditEvent<Bill, Date>>() {
@Override
public void handle(CellEditEvent<Bill, Date> t) {
// I NEED TO BE ABLE:
// (1) Read the 'paymentDate' field of the same row.
// (2) Change the color of the background of this
// 'expirationDate' cell, in this row.
Bill bill = (Bill) t.getTableView()
.getItems()
.get(t.getTablePosition().getRow());
bill.setExpirationDate(t.getNewValue());
Date paymentDate = bill.getPaymentDate();
long now = new Date().getTime();
now -= now % MILLISECONDS_PER_DAY;
long expirationMoment = bill.getExpirationDate().getTime();
if (paymentDate == null) {
long daysLeft = (expirationMoment - now) /
MILLISECONDS_PER_DAY;
} else {
long paymentMoment = paymentDate.getTime();
paymentMoment -= paymentMoment % MILLISECONDS_PER_DAY;
long days = (expirationMoment - paymentMoment) /
MILLISECONDS_PER_DAY;
System.out.println("Days paid before: " + days);
}
}
}
);
tableColumnPaymentDate.setOnEditCommit(
new EventHandler<CellEditEvent<Bill, Date>>() {
@Override
public void handle(CellEditEvent<Bill, Date> t) {
((Bill) t.getTableView()
.getItems()
.get(t.getTablePosition()
.getRow()))
.setPaymentDate(t.getNewValue());
}
}
);
}
...
}
运行应用程序所需的一切都是here。
更具体地说,每当我设置到期日期单元格的背景颜色时,我找不到查看同一行中另一个单元格的方法。
答案 0 :(得分:0)
最简洁的方法是使用行工厂来更改表行上的样式类或伪类。然后在单元格上设置一个固定的样式类。
在我的示例中,我使用LocalDate
代替遗留Date
类型;你可以做点什么
PseudoClass nearlyExpired = PseudoClass.getPseudoClass("nearly-expired");
table.setRowFactory(tv -> {
TableRow<Bill> row = new TableRow<>() ;
BooleanProperty nearlyDueProperty = new SimpleBooleanProperty();
nearlyDueProperty.addListener((obs, wasNearlyDue, isNearlyDue) ->
row.pseudoClassStateChanged(nearlyExpired, isNearlyDue));
row.itemProperty().addListener((obs, oldBill, newBill) -> {
nearlyDueProperty.unbind();
if (newBill == null) {
nearlyDueProperty.set(false);
} else {
// bind nearlyDueProperty to the time between the current Bill's
// paymentDate and expirationDate
// true if less than 7 days, false otherwise:
nearlyDueProperty.bind(Bindings.createBooleanBinding(() ->
newBill.getExpirationDate().minusDays(7).isBefore(newBill.getPaymentDate()),
newBill.expirationDateProperty(), newBill.paymentDateProperty()));
}
});
return row ;
});
然后对于列本身你只需要
LocalDateStringConverter converter = new LocalDateStringConverter();
Callback<TableColumn<Bill, LocalDate>, TableCell<Bill, LocalDate>> defaultCellFactory = TextFieldTableCell.forTableColumn(converter);
expirationDateCol.setCellFactory(tc -> {
TableCell<Bill, LocalDate> cell = defaultCellFactory.call(tc);
cell.getStyleClass().add("expiration-cell");
return cell ;
});
最后你可以用
附加一个外部样式表.table-row-cell:nearly-expired .expiration-cell {
-fx-background-color: red ;
}
显然,您可以按照自己喜欢的方式定义样式。
这是一个完整的例子:
import java.time.LocalDate;
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.converter.LocalDateStringConverter;
public class BillingTable extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Bill> table = new TableView<>();
table.setEditable(true);
PseudoClass nearlyExpired = PseudoClass.getPseudoClass("nearly-expired");
table.setRowFactory(tv -> {
TableRow<Bill> row = new TableRow<>() ;
BooleanProperty nearlyDueProperty = new SimpleBooleanProperty();
nearlyDueProperty.addListener((obs, wasNearlyDue, isNearlyDue) ->
row.pseudoClassStateChanged(nearlyExpired, isNearlyDue));
row.itemProperty().addListener((obs, oldBill, newBill) -> {
nearlyDueProperty.unbind();
if (newBill == null) {
nearlyDueProperty.set(false);
} else {
nearlyDueProperty.bind(Bindings.createBooleanBinding(() ->
newBill.getExpirationDate().minusDays(7).isBefore(newBill.getPaymentDate()),
newBill.expirationDateProperty(), newBill.paymentDateProperty()));
}
});
return row ;
});
TableColumn<Bill, LocalDate> paymentDateCol = column("Payment Date", Bill::paymentDateProperty);
table.getColumns().add(paymentDateCol);
LocalDateStringConverter converter = new LocalDateStringConverter();
Callback<TableColumn<Bill, LocalDate>, TableCell<Bill, LocalDate>>
defaultCellFactory = TextFieldTableCell.forTableColumn(converter);
paymentDateCol.setCellFactory(defaultCellFactory);
TableColumn<Bill, LocalDate> expirationDateCol = column("Expiration Date", Bill::expirationDateProperty);
table.getColumns().add(expirationDateCol);
expirationDateCol.setCellFactory(tc -> {
TableCell<Bill, LocalDate> cell = defaultCellFactory.call(tc);
cell.getStyleClass().add("expiration-cell");
return cell ;
});
Random rng = new Random();
for (int i = 1; i <= 20 ; i++) {
LocalDate now = LocalDate.now();
LocalDate payment = now.plusDays(rng.nextInt(5));
LocalDate expiration = payment.plusDays(rng.nextInt(14));
table.getItems().add(new Bill(payment, expiration));
}
Scene scene = new Scene(table);
scene.getStylesheets().add("payment-table.css");
primaryStage.setScene(scene);
primaryStage.show();
}
private static <S,T> TableColumn<S,T> column(String title, Function<S,Property<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Bill {
private final ObjectProperty<LocalDate> paymentDate = new SimpleObjectProperty<>();
private final ObjectProperty<LocalDate> expirationDate = new SimpleObjectProperty<>();
// other properties...
public Bill(LocalDate paymentDate, LocalDate expirationDate) {
setPaymentDate(paymentDate);
setExpirationDate(expirationDate);
}
public final ObjectProperty<LocalDate> paymentDateProperty() {
return this.paymentDate;
}
public final java.time.LocalDate getPaymentDate() {
return this.paymentDateProperty().get();
}
public final void setPaymentDate(final java.time.LocalDate paymentDate) {
this.paymentDateProperty().set(paymentDate);
}
public final ObjectProperty<LocalDate> expirationDateProperty() {
return this.expirationDate;
}
public final java.time.LocalDate getExpirationDate() {
return this.expirationDateProperty().get();
}
public final void setExpirationDate(final java.time.LocalDate expirationDate) {
this.expirationDateProperty().set(expirationDate);
}
}
public static void main(String[] args) {
launch(args);
}
}
上面的样式表在payment-table.css中。