我有一个包含数量和价格列的表格,可以编辑而不是禁用。该表填充了ObservableList<Collection>
。 Collection
对象具有boolean
属性paid
。我要实现的是,只要paid
为真,就禁用价格和数量表格,并且不可编辑。
这是我到目前为止所做的:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.FloatProperty;
import javafx.beans.property.ReadOnlyFloatProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
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.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.converter.FloatStringConverter;
public class CollectionTable extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
TableView<Collection> tv = new TableView();
tv.setEditable(true);
TableColumn<Collection, Number> colQty = createQuantityColumn();
colQty.setCellFactory(
new Callback<TableColumn<Collection, Number>, TableCell<Collection, Number>>() {
@Override
public TableCell<Collection, Number> call(TableColumn<Collection, Number> paramTableColumn) {
return new TextFieldTableCell<Collection, Number>() {
@Override
public void updateItem(Number s, boolean b) {
super.updateItem(s, b);
TableRow row = getTableRow();
if (row != null) {
Collection item = (Collection) row.getItem();
//Test for disable condition
if (item != null && item.isPaid()) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-text-fill: grey;-fx-border-color: red");
}
}
}
};
}
});
TableColumn<Collection, Number> colPrice = createPriceColumn();
colPrice.setCellFactory(
new Callback<TableColumn<Collection, Number>, TableCell<Collection, Number>>() {
@Override
public TableCell<Collection, Number> call(TableColumn<Collection, Number> paramTableColumn) {
return new TextFieldTableCell<Collection, Number>() {
@Override
public void updateItem(Number s, boolean b) {
super.updateItem(s, b);
TableRow row = getTableRow();
if (row != null) {
Collection item = (Collection) row.getItem();
//Test for disable condition
if (item != null && !item.isPaid()) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-text-fill: grey;-fx-border-color: red");
}
}
}
};
}
});
TableColumn<Collection, Number> colAmount = createAmountColumn();
TableColumn<Collection, String> colMno = createMNOColumn();
tv.getColumns().addAll(colMno, colQty, colPrice, colAmount);
tv.getItems().addAll(getCollection());
Scene scene = new Scene(new BorderPane(tv), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private TableColumn createQuantityColumn() {
TableColumn<Collection, Float> colQty = new TableColumn("Quantity");
colQty.setMinWidth(25);
colQty.setId("colQty");
colQty.setCellFactory(TextFieldTableCell.<Collection, Float>forTableColumn(new FloatStringConverter()));
colQty.setCellValueFactory(cellData -> cellData.getValue().quantityProperty().asObject());
colQty.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Collection, Float>>() {
@Override
public void handle(TableColumn.CellEditEvent<Collection, Float> t) {
}
});
return colQty;
}
private TableColumn createPriceColumn() {
TableColumn<Collection, Float> colPrice = new TableColumn("Price");
colPrice.setMinWidth(25);
colPrice.setId("colPrice");
colPrice.setCellFactory(TextFieldTableCell.<Collection, Float>forTableColumn(new FloatStringConverter()));
colPrice.setCellValueFactory(cellData -> cellData.getValue().priceProperty().asObject());
colPrice.setOnEditStart(new EventHandler<TableColumn.CellEditEvent<Collection, Float>>() {
@Override
public void handle(TableColumn.CellEditEvent<Collection, Float> t) {
Collection c = ((Collection) t.getTableView().getItems().get(t.getTablePosition().getRow()));
c.setPrice(Math.abs(c.getPrice()));
}
});
colPrice.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Collection, Float>>() {
@Override
public void handle(TableColumn.CellEditEvent<Collection, Float> t) {
Collection c = ((Collection) t.getTableView().getItems().get(t.getTablePosition().getRow()));
c.setPrice(Math.abs((float)t.getNewValue()));
//int i = collectionHandler.updateCollection(c);
}
});
return colPrice;
}
private TableColumn createAmountColumn() {
TableColumn<Collection, Float> colAmount = new TableColumn("Amount");
colAmount.setMinWidth(25);
colAmount.setId("colAmount");
colAmount.setCellValueFactory(cellData -> cellData.getValue().amountProperty().asObject());
return colAmount;
}
private TableColumn createMNOColumn() {
TableColumn colMNO = new TableColumn("M/NO");
colMNO.setMinWidth(25);
colMNO.setId("colMNO");
colMNO.setCellValueFactory(new PropertyValueFactory("mno"));
return colMNO;
}
private List<Collection> getCollection(){
List<Collection> collections = new ArrayList<>();
collections.add(new Collection(1, 10, "1", false));
collections.add(new Collection(2, 10, "12", true));
collections.add(new Collection(3, 10, "123", true));
collections.add(new Collection(4, 10, "312", true));
collections.add(new Collection(5, 10, "311", false));
collections.add(new Collection(6, 10, "322", true));
collections.add(new Collection(7, 10, "333", true));
collections.add(new Collection(8, 10, "321", false));
collections.add(new Collection(9, 10, "456", true));
collections.add(new Collection(10, 10, "551", true));
collections.add(new Collection(11, 10, "515", false));
collections.add(new Collection(12, 10, "134", true));
collections.add(new Collection(13, 10, "789", true));
collections.add(new Collection(14, 10, "879", false));
collections.add(new Collection(15, 10, "987", true));
collections.add(new Collection(16, 10, "856", true));
collections.add(new Collection(17, 10, "956", true));
collections.add(new Collection(18, 10, "589", true));
collections.add(new Collection(19, 10, "852", false));
collections.add(new Collection(20, 10, "456", false));
collections.add(new Collection(21, 10, "623", true));
collections.add(new Collection(22, 10, "147", false));
collections.add(new Collection(23, 10, "125", true));
collections.add(new Collection(24, 10, "258", false));
collections.add(new Collection(25, 10, "325", true));
collections.add(new Collection(26, 10, "753", true));
collections.add(new Collection(27, 10, "357", false));
collections.add(new Collection(28, 10, "159", false));
return collections;
}
public class Collection{
private final FloatProperty quantity = new SimpleFloatProperty();
private final FloatProperty price = new SimpleFloatProperty();
private final FloatProperty amount = new SimpleFloatProperty();
private final BooleanProperty paid = new SimpleBooleanProperty(false);
private String mno;
public Collection(){
this(0f, 0f, null, false);
}
public Collection(float quantity, float price, String mno, boolean paid) {
setQuantity(quantity);
setPrice(price);
setMno(mno);
setPaid(paid);
this.amount.bind(this.quantity.multiply(this.price));
}
public String getMno() {
return mno;
}
public void setMno(String mno) {
this.mno = mno;
}
public float getQuantity() {
return quantityProperty().get();
}
public void setQuantity(float quantity) {
quantityProperty().set(quantity);
}
public FloatProperty quantityProperty() {
return quantity ;
}
public float getPrice() {
return priceProperty().get();
}
public void setPrice(float price) {
priceProperty().set(price);
}
public FloatProperty priceProperty() {
return price ;
}
public float getAmount() {
return amountProperty().get();
}
public ReadOnlyFloatProperty amountProperty() {
return amount ;
}
public BooleanProperty paidProperty() {
return paid;
}
public void setPaid(boolean approved) {
this.paid.set(approved);
}
public boolean isPaid() {
return paid.get();
}
}
}
我的代码存在的问题是,当我向下滚动表格时,先前已启用且可编辑的单元格将更改为已禁用且无法编辑。
答案 0 :(得分:2)
第一个问题是,当一个单元从一个单元被重新使用时,你不会重置状态。当您滚动时,这将发生。如果一个单元格先前已用于表示“付费”字样的行中。 item(因此它被禁用,不可编辑,并且有一个红色边框),并被重用于&#34; unpaid&#34; item,您的updateItem()
方法不会更改可编辑或禁用状态(或样式)。所以你应该有类似的东西:
if (item != null && item.isPaid()) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-text-fill: grey;-fx-border-color: red");
} else {
setDisable(false);
setEditable(true);
setStyle("");
}
第二个问题是您无法控制更新单元格状态的顺序。似乎有时在调用updateItem()
方法之后更新了行属性,因此最终会出现不一致的状态。您可以安全地使用单元格索引从表格数据中获取正确的项目。
另请注意,由于两个单元工厂都相同,因此无需复制代码。这对我有用:
@Override
public void start(Stage primaryStage) throws Exception {
TableView<Collection> tv = new TableView();
tv.setEditable(true);
TableColumn<Collection, Number> colQty = createQuantityColumn();
Callback<TableColumn<Collection, Number>, TableCell<Collection, Number>> cellFactory = new Callback<TableColumn<Collection, Number>, TableCell<Collection, Number>>() {
@Override
public TableCell<Collection, Number> call(TableColumn<Collection, Number> paramTableColumn) {
return new TextFieldTableCell<Collection, Number>() {
@Override
public void updateItem(Number s, boolean b) {
super.updateItem(s, b);
if (! isEmpty()) {
Collection item = getTableView().getItems().get(getIndex());
// Test for disable condition
if (item != null && item.isPaid()) {
setDisable(true);
setEditable(false);
this.setStyle("-fx-text-fill: grey;-fx-border-color: red");
} else {
setDisable(false);
setEditable(true);
setStyle("");
}
}
}
};
}
};
colQty.setCellFactory(cellFactory);
TableColumn<Collection, Number> colPrice = createPriceColumn();
colPrice.setCellFactory(cellFactory);
TableColumn<Collection, Number> colAmount = createAmountColumn();
TableColumn<Collection, String> colMno = createMNOColumn();
tv.getColumns().addAll(colMno, colQty, colPrice, colAmount);
tv.getItems().addAll(getCollection());
Scene scene = new Scene(new BorderPane(tv), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}