Javafx:检测对tableView所做的所有更改,包括在任何表行上添加/删除表行和单元格编辑 [英] Javafx: Detect ALL changes made to tableView including addition/deletion of table rows and cell edits on any table rows

查看:97
本文介绍了Javafx:检测对tableView所做的所有更改,包括在任何表行上添加/删除表行和单元格编辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于我有 tableView ,我如何跟踪所有更改,即添加/删除新行,其中一个表格单元格具有值已更改,并在检测到任何这些更改时触发相同的事件?

Given that I have a tableView, how can I track all the changes, i.e. a new row is added / deleted, one of the table cells has its value changed, and fire off the same event when any of these changes are detected ?

目前,我在下面有以下代码,仅管理如果我添加一行,检测更改。当我编辑任何行的表格单元格时以及删除行时,它无法检测到更改。

At the moment, I have the following code below, which only manages to detect change if I add in a row. It is not able to detect changes when I edit a table cell of any row and when I delete a row.

    ObservableList<Trade> observableListOfTrades =FXCollections.observableArrayList();


    observableListOfTrades.add(newTrade);  
fxTransactionLog.getItems().add(observableListOfTrades.get(observableListOfTrades.size()-1));


        observableListOfTrades.addListener(new ListChangeListener() {
            @Override
            public void onChanged(ListChangeListener.Change change) {
                System.out.println("Detected a change! ");
            }
        });

根据要求,我发布了我的交易 Class

As requested, I am posting my Trade Class

public class Trade{

// properties
private ObjectProperty<LocalDate> transactionDate;
private StringProperty itemName;
private StringProperty buySell;
private DoubleProperty volume;
private DoubleProperty price;
private DoubleBinding transactionFee;


public Trade(BuySell buySell, LocalDate transactionDate, double volume, double price){
    this.buySell = new SimpleStringProperty(buySell.toString());
    this.itemName = new SimpleStringProperty("testing");
    this.transactionDate = new SimpleObjectProperty<LocalDate>(transactionDate);
    this.volume = new SimpleDoubleProperty(volume);
    this.price = new SimpleDoubleProperty(price);
}

// getters
public String getBuySell(){
    return this.buySell.get();
}

// return Property Object
public StringProperty buySellProperty(){
    return this.buySell;
}

// setters
public void setBuySell(String buySell){
    this.buySell.set(buySell);
}

public LocalDate getTransactionDate(){
    return this.transactionDate.getValue();
}

public ObjectProperty<LocalDate> transactionDateProperty(){
    return this.transactionDate;
}

public void setTransactionDate(LocalDate transactionDate){
    this.transactionDate.set(transactionDate);
}


public double getVolume(){
    return this.volume.get();
}

public DoubleProperty volumeProperty(){
    return this.volume;
}

public void setVolume(double volume){
    this.volume.set(volume);
}


public double getPrice(){
    return this.price.get();
}   

public DoubleProperty priceProperty(){
    return this.price;
}

public void setPrice(double price){
    this.price.set(price);
}

public String getItemName(){
    return this.itemName.getValue();
}


public double getTransactionFee(){
        this.transactionFee = this.price.multiply(this.volume).multiply(0.15);
        return this.transactionFee.getValue();
}

public DoubleBinding transactionFeeProperty(){
    return this.transactionFee;
}



public String toString(){
    return "Buy: " + getBuySell() + ", Transasction date: " + getTransactionDate() + ", Volume: " + getVolume() + ", Price: " + getPrice() + ", Transaction fee: " + getTransactionFee() ;
}
}


推荐答案

您的听众应该回应被删除的项目;如果不是,则可能是您未显示的代码有问题。

Your listener should be responding to items being removed; if it's not, then there may be something wrong with the code you haven't shown.

对于 ListChangeListener 要响应属于列表元素的属性的更新,您需要创建指定提取器

For a ListChangeListener to respond to updates to properties belonging to elements of the list, you need to create your list specifying an extractor.

提取器是一个函数,它接受列表的元素,并返回一个可观察值的数组。然后该列表会观察该数组中的所有值,如果它们发生更改,则会向列表的侦听器触发更新事件。

The extractor is a function that takes an element of the list, and returns an array of observable values. The list then observes all the values in that array, and if they change, fires update events to listeners of the list.

因此,如果您希望通知您的侦听器如果任何属性发生了变化,你会做

So, if you wanted your listener to be notified if any of the properties changed, you would do

ObservableList<Trade> observableListOfTrades =FXCollections.observableArrayList(trade ->
    new Observable[] {
        trade.transactionDateProperty(),
        trade.itemNameProperty(),
        trade.buySellProperty(),
        trade.volumeProperty(),
        trade.priceProperty().
        trade.transactionFeeProperty()
    });

这是一个完整的例子,使用通常的联系表示例:

Here is a complete example, using the usual "contact table" example:

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableViewWithUpdateListenerExample extends Application {

    @Override
    public void start(Stage primaryStage) {

        // Create an observable list with an extractor. This will ensure
        // listeners on the list receive notifications if any of the
        // properties returned by the extractor belonging to a list element
        // are changed:

        ObservableList<Person> data = FXCollections.observableArrayList(person ->
            new Observable[] {
                    person.firstNameProperty(),
                    person.lastNameProperty(),
                    person.emailProperty()
            });

        data.addListener((Change<? extends Person> c) -> {
           while (c.next()) {
               if (c.wasAdded()) {
                   System.out.println("Added:");
                   c.getAddedSubList().forEach(System.out::println);
                   System.out.println();
               }
               if (c.wasRemoved()) {
                   System.out.println("Removed:");
                   c.getRemoved().forEach(System.out::println);
                   System.out.println();
               }
               if (c.wasUpdated()) {
                   System.out.println("Updated:");
                   data.subList(c.getFrom(), c.getTo()).forEach(System.out::println);
                   System.out.println();
               }
           }
        });

        data.addAll(
                new Person("Jacob", "Smith", "jacob.smith@example.com"),
                new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
                new Person("Ethan", "Williams", "ethan.williams@example.com"),
                new Person("Emma", "Jones", "emma.jones@example.com"),
                new Person("Michael", "Brown", "michael.brown@example.com")
        );

        TableView<Person> tableView = new TableView<>();
        tableView.setEditable(true);
        tableView.setItems(data);

        tableView.getColumns().add(column("First Name", Person::firstNameProperty));
        tableView.getColumns().add(column("Last Name", Person::lastNameProperty));
        tableView.getColumns().add(column("Email", Person::emailProperty));

        TextField firstNameTF = new TextField();
        TextField lastNameTF = new TextField();
        TextField emailTF = new TextField();
        Button addButton = new Button("Add");
        addButton.setOnAction(e -> {
            Person person = new Person(firstNameTF.getText(), lastNameTF.getText(), emailTF.getText());
            firstNameTF.setText("");
            lastNameTF.setText("");
            emailTF.setText("");
            data.add(person);
        });

        GridPane editPane = new GridPane();
        editPane.addRow(0,  new Label("First Name:"), firstNameTF);
        editPane.addRow(1,  new Label("Last Name:"), lastNameTF);
        editPane.addRow(2,  new Label("Email:"), emailTF);
        editPane.add(addButton, 0, 3, 2, 1);
        ColumnConstraints leftCol = new ColumnConstraints();
        leftCol.setHalignment(HPos.RIGHT);
        leftCol.setHgrow(Priority.NEVER);
        editPane.setHgap(10);
        editPane.setVgap(5);
        editPane.getColumnConstraints().addAll(leftCol, new ColumnConstraints());

        Button deleteButton = new Button("Delete");
        deleteButton.setOnAction(e -> data.remove(tableView.getSelectionModel().getSelectedItem()));
        deleteButton.disableProperty().bind(Bindings.isEmpty(tableView.getSelectionModel().getSelectedItems()));

        VBox root = new VBox(10, tableView, editPane, deleteButton);
        root.setAlignment(Pos.CENTER);

        primaryStage.setScene(new Scene(root, 800, 600));
        primaryStage.show();
    }

    private TableColumn<Person, String> column(String title, Function<Person, ObservableValue<String>> property) {
        TableColumn<Person, String> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        col.setCellFactory(TextFieldTableCell.forTableColumn());
        return col ;
    }

    public static class Person {
        private final StringProperty firstName = new SimpleStringProperty() ;
        private final StringProperty lastName = new SimpleStringProperty() ;
        private final StringProperty email = new SimpleStringProperty() ;

        public Person(String firstName, String lastName, String email) {
            setFirstName(firstName);
            setLastName(lastName);
            setEmail(email);
        }

        public final StringProperty firstNameProperty() {
            return this.firstName;
        }

        public final java.lang.String getFirstName() {
            return this.firstNameProperty().get();
        }

        public final void setFirstName(final java.lang.String firstName) {
            this.firstNameProperty().set(firstName);
        }

        public final StringProperty lastNameProperty() {
            return this.lastName;
        }

        public final java.lang.String getLastName() {
            return this.lastNameProperty().get();
        }

        public final void setLastName(final java.lang.String lastName) {
            this.lastNameProperty().set(lastName);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final java.lang.String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final java.lang.String email) {
            this.emailProperty().set(email);
        }

        @Override
        public String toString() {
            return getFirstName() + " " + getLastName() + " (" + getEmail() +")";
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于Javafx:检测对tableView所做的所有更改,包括在任何表行上添加/删除表行和单元格编辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆