当基础数据更改时,TreeTableView 单元格不会更新

TreeTableView cells does not get updated when underlying data changes

我正在编写一个在 JFXTreeTableView 中显示实时报价的市场观察程序,但是当我更新 ObservableList 中的数据时,它不会在 JFXTreeTableView 中更新。 changeDataDemo() 方法实际上跟踪价格变化并且工作正常(我正在使用 RethinkDB changefeeds 来完成它。)但是我已经删除了此处的 changefeed 代码以提高可读性。有一种方法可以将行添加到 TreeTableView 并且工作正常,但我已从此处删除了代码。

这是我的代码:

public class MainWindow implements Initializable {
    private ObservableList<MarketWatchEntry> marketWatchEntries = FXCollections.observableArrayList();
    private JFXTreeTableColumn<MarketWatchEntry, String> instrument_token_col;
    private JFXTreeTableColumn<MarketWatchEntry, String> exchange_col;
    private JFXTreeTableColumn<MarketWatchEntry, String> instrument_type_col;
    private JFXTreeTableColumn<MarketWatchEntry, String> symbol_col;
    private JFXTreeTableColumn<MarketWatchEntry, String> expiry_col;
    private JFXTreeTableColumn<MarketWatchEntry, Number> buy_qty_col;
    private JFXTreeTableColumn<MarketWatchEntry, Number> buy_price_col;
    private JFXTreeTableColumn<MarketWatchEntry, Number> seller_price_col;
    private JFXTreeTableColumn<MarketWatchEntry, Number> sell_qty_col;


    @FXML
    private JFXTreeTableView<MarketWatchEntry> MarketWatch;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        populateMarketWatch();
    }

    private void populateMarketWatch() {
        instrument_token_col = new JFXTreeTableColumn<>("Instrument Token");
        instrument_token_col.setPrefWidth(80);
        instrument_token_col.setVisible(false);
        instrument_token_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, String> param) -> param.getValue().getValue().instrument_token);

        exchange_col = new JFXTreeTableColumn<>("Exchange");
        exchange_col.setPrefWidth(80);
        exchange_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, String> param) -> param.getValue().getValue().exchange);

        instrument_type_col = new JFXTreeTableColumn<>("Instrument");
        instrument_type_col.setPrefWidth(80);
        instrument_type_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, String> param) -> param.getValue().getValue().instrument_type);

        symbol_col = new JFXTreeTableColumn<>("Symbol");
        symbol_col.setPrefWidth(80);
        symbol_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, String> param) -> param.getValue().getValue().trading_symbol);

        expiry_col = new JFXTreeTableColumn<>("Expiry");
        expiry_col.setPrefWidth(80);
        expiry_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, String> param) -> param.getValue().getValue().expiry);

        buy_qty_col = new JFXTreeTableColumn<>("Buy Qty");
        buy_qty_col.setPrefWidth(80);
        buy_qty_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, Number> param) -> param.getValue().getValue().buy_qty);

        buy_price_col = new JFXTreeTableColumn<>("Buyer Price");
        buy_price_col.setPrefWidth(80);
        buy_price_col.setCellValueFactory((JFXTreeTableColumn.CellDataFeatures<MarketWatchEntry, Number> param) -> param.getValue().getValue().buyer_price);

        seller_price_col = new JFXTreeTableColumn<>("Seller Price");
        seller_price_col.setPrefWidth(80);
        seller_price_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, Number> param) -> param.getValue().getValue().seller_price);

        sell_qty_col = new JFXTreeTableColumn<>("Sell Qty");
        sell_qty_col.setPrefWidth(80);
        sell_qty_col.setCellValueFactory((TreeTableColumn.CellDataFeatures<MarketWatchEntry, Number> param) -> param.getValue().getValue().sell_qty);

      final TreeItem<MarketWatchEntry> root = new RecursiveTreeItem<>(marketWatchEntries, RecursiveTreeObject::getChildren);
        MarketWatch.getColumns().setAll(instrument_token_col, exchange_col, instrument_type_col, symbol_col, expiry_col,
                buy_qty_col, buy_price_col, seller_price_col, sell_qty_col, ltp_col, ltq_col, open_price_col, high_price_col,
                low_price_col, close_price_col, average_price_col, change_col, net_change_col);
        MarketWatch.setRoot(root);
        MarketWatch.setShowRoot(false);
    }

    private void changeDataDemo() {
        marketWatchEntries.get(0).buyer_price = new SimpleDoubleProperty(100);
    }
}

我删除了不相关的代码块以提高可读性。 我的问题是如何让 TreeTableView 在使用新数据更新集合时更新所有单元格。

MarketWatchEntry class

class MarketWatchEntry extends RecursiveTreeObject<MarketWatchEntry> {
        StringProperty instrument_token;
        StringProperty exchange;
        StringProperty instrument_type;
        StringProperty trading_symbol;
        StringProperty expiry;
        DoubleProperty buy_qty;
        DoubleProperty buyer_price;
        DoubleProperty seller_price;
        DoubleProperty sell_qty;
        DoubleProperty last_price;
        DoubleProperty last_qty;
        DoubleProperty open_price;
        DoubleProperty high_price;
        DoubleProperty low_price;
        DoubleProperty close_price;
        DoubleProperty average_price;
        DoubleProperty change;
        DoubleProperty net_change;

        public MarketWatchEntry(String instrument_token, String exchange, String instrument_type, String trading_symbol,
                                String expiry, double buy_qty, double buy_price, double sell_price, double sell_qty,
                                double last_price, double last_qty, double open_price, double high_price, double low_price,
                                double close_price, double average_price, double change, double net_change) {
            this.instrument_token = new SimpleStringProperty(instrument_token);
            this.exchange = new SimpleStringProperty(exchange);
            this.instrument_type = new SimpleStringProperty(instrument_type);
            this.trading_symbol = new SimpleStringProperty(trading_symbol);
            this.expiry = new SimpleStringProperty(expiry);
            this.buy_qty = new SimpleDoubleProperty(buy_qty);
            this.buyer_price = new SimpleDoubleProperty(buy_price);
            this.sell_qty = new SimpleDoubleProperty(sell_qty);
            this.seller_price = new SimpleDoubleProperty(sell_price);
            this.last_price = new SimpleDoubleProperty(last_price);
            this.last_qty = new SimpleDoubleProperty(last_qty);
            this.open_price = new SimpleDoubleProperty(open_price);
            this.high_price = new SimpleDoubleProperty(high_price);
            this.low_price = new SimpleDoubleProperty(low_price);
            this.close_price = new SimpleDoubleProperty(close_price);
            this.average_price = new SimpleDoubleProperty(average_price);
            this.change = new SimpleDoubleProperty(change);
            this.net_change = new SimpleDoubleProperty(net_change);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            return this.instrument_token.getValue().equals(((MarketWatchEntry) obj).instrument_token.getValue());
        }

        @Override
        public int hashCode() {
            return 7 + 5 * Integer.valueOf(instrument_token.getValue());
        }


    }

问题出在您的 changeDataDemo 方法中:

private void changeDataDemo() {
    marketWatchEntries.get(0).buyer_price = new SimpleDoubleProperty(100);
}

您正在创建属性的新实例,而不是更改它们的值。

像这样的东西有效:

private void changeDataDemo() {
    marketWatchEntries.get(0).buyer_price.set(100);
}

但建议在您的实体上提供 setters/getters class:

class MarketWatchEntry extends RecursiveTreeObject<MarketWatchEntry> {
    private final DoubleProperty buyer_price;
    ...

    public MarketWatchEntry(String instrument_token, String exchange, String instrument_type, String trading_symbol,
                            String expiry, double buy_qty, double buy_price, double sell_price, double sell_qty) {
        ...
        this.buyer_price = new SimpleDoubleProperty(buy_price);
        ...  
    }

    public final DoubleProperty buyer_priceProperty() {
        return buyer_price;
    }

    public final double getBuyer_price() {
        return buyer_price.get();
    }

    public final void setBuyer_price(double value) {
        buyer_price.set(value);
    }
    ...
 }

所以你可以打电话:

private void changeDataDemo() {
    marketWatchEntries.get(0).setBuyer_price(100);
}