Home > OS >  Use a listener to get selected rows (mails) in tableView and add mails to my list of mails
Use a listener to get selected rows (mails) in tableView and add mails to my list of mails

Time:10-26

I have a tableView of id, name, mail, phone and select. I wanna get all selected row of my tableView and add selected mail to my email list in my model class. I read : screenshot

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.collections.transformation.FilteredList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Arrays;

/**
 * https://stackoverflow.com/a/69712532/230513
 */
public class MailingListViewApp extends Application {

    private final ObservableList<Person> people = FXCollections.observableList(
            Arrays.asList(
                    new Person("Ralph", "Alpher", true, "[email protected]"),
                    new Person("Hans", "Bethe", false, "[email protected]"),
                    new Person("George", "Gammow", true, "[email protected]"),
                    new Person("Paul", "Dirac", false, "[email protected]"),
                    new Person("Albert", "Einstein", true, "[email protected]")
            ),
            person -> new Observable[] { person.invitedProperty() }
    );

    private final ObservableList<Person> mailingList = new FilteredList<>(
            people,
            person -> person.invitedProperty().get()
    );

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

    @Override
    public void start(Stage stage) {
        final TableView<Person> mailingListSelectionTableView =
                createMailingListSelectionTableView();

        ListView<Person> mailingListView =
                createMailingListView();

        final VBox vbox = new VBox(
                10,
                new TitledPane("Candidates", mailingListSelectionTableView),
                new TitledPane("Mailing List", mailingListView)
        );
        vbox.setPadding(new Insets(10));

        stage.setScene(new Scene(vbox));
        stage.show();
    }

    private TableView<Person> createMailingListSelectionTableView() {
        final TableView<Person> selectionTableView = new TableView<>(people);
        selectionTableView.setPrefSize(440, 180);

        TableColumn<Person, String> firstName = new TableColumn<>("First Name");
        firstName.setCellValueFactory(cd -> cd.getValue().firstNameProperty());
        selectionTableView.getColumns().add(firstName);

        TableColumn<Person, String> lastName = new TableColumn<>("Last Name");
        lastName.setCellValueFactory(cd -> cd.getValue().lastNameProperty());
        selectionTableView.getColumns().add(lastName);

        TableColumn<Person, Boolean> invited = new TableColumn<>("Invited");
        invited.setCellValueFactory(cd -> cd.getValue().invitedProperty());
        invited.setCellFactory(CheckBoxTableCell.forTableColumn(invited));
        selectionTableView.getColumns().add(invited);

        TableColumn<Person, String> email = new TableColumn<>("Email");
        email.setCellValueFactory(cd -> cd.getValue().emailProperty());
        selectionTableView.getColumns().add(email);

        selectionTableView.setEditable(true);
        return selectionTableView;
    }

    private ListView<Person> createMailingListView() {
        ListView<Person> mailingListView = new ListView<>();
        mailingListView.setCellFactory(param -> new ListCell<>() {
            @Override
            protected void updateItem(Person item, boolean empty) {
                super.updateItem(item, empty);

                if (empty || item == null || item.emailProperty().get() == null) {
                    setText(null);
                } else {
                    setText(item.emailProperty().get());
                }
            }
        });
        mailingListView.setItems(mailingList);
        mailingListView.setPrefHeight(160);
        return mailingListView;
    }

    private static class Person {

        private final StringProperty firstName;
        private final StringProperty lastName;
        private final BooleanProperty invited;
        private final StringProperty email;

        private Person(String fName, String lName, boolean invited, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.invited = new SimpleBooleanProperty(invited);
            this.email = new SimpleStringProperty(email);
        }

        public StringProperty firstNameProperty() {
            return firstName;
        }

        public StringProperty lastNameProperty() {
            return lastName;
        }

        public BooleanProperty invitedProperty() {
            return invited;
        }

        public StringProperty emailProperty() {
            return email;
        }
    }
}

Is the FilteredList Solution appropriate for you?

It is hard to say. It is one potential approach.

As trashgod notes in the comments, the best approach for your application may depend on your overall UI and application architecture.

For example, rather than using the filtered list, you could have a Save button or some other commit point, where it checks a dirty flag such as the modelChanged flag in trashgod's solution (or even do away with the listener/modelChanged concept completely). Then just iterate over the original list extracting any items which are selected at that point in time, and reflect those values back in your model (e.g. commit to the database). Such would be a kind of MVVM approach, where the observable list for selection is just involved as the view-model (VM) and the separate list of committed mailing information is the model (M).

Even if you did use the separate save point approach outlined above, perhaps the addition of the filtered list could still ease the conversion task for you, as all you would need to do is look at all items in the filtered list.

Also, the filtered list could be used in other functions of the app, such as the mailing list view displayed in this solution.

CodePudding user response:

As outlined image

import java.util.Arrays;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

/**
 * https://stackoverflow.com/a/69715448/230513
 * https://stackoverflow.com/q/69711881/230513
 * https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm
 * https://docs.oracle.com/javase/8/javafx/properties-binding-tutorial/binding.htm#JFXBD107
 * https://stackoverflow.com/a/38050982/230513
 * https://stackoverflow.com/a/25204271/230513
 */
public class TableViewTest extends Application {

    private final ObservableList<Person> model = FXCollections.observableList(
        Arrays.asList(
            new Person("Ralph", "Alpher", true, "[email protected]"),
            new Person("Hans", "Bethe", false, "[email protected]"),
            new Person("George", "Gammow", true, "[email protected]"),
            new Person("Paul", "Dirac", false, "[email protected]"),
            new Person("Albert", "Einstein", true, "[email protected]")
        ), p -> p.extract());

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

    @Override
    public void start(Stage stage) {
        stage.setTitle("Table View Sample");
        stage.setWidth(640);
        stage.setHeight(480);

        final TableView<Person> table = new TableView<>(model);
        final Label label = new Label("Address Book");
        label.setFont(Font.font("Serif", 20));
        final Label status = new Label(calcuateStatus());

        TableColumn<Person, String> firstName = new TableColumn<>("First Name");
        firstName.setCellValueFactory(cd -> cd.getValue().firstNameProperty());
        table.getColumns().add(firstName);

        TableColumn<Person, String> lastName = new TableColumn<>("Last Name");
        lastName.setCellValueFactory(cd -> cd.getValue().lastNameProperty());
        table.getColumns().add(lastName);

        TableColumn<Person, Boolean> invited = new TableColumn<>("Invited");
        invited.setCellValueFactory(cd -> cd.getValue().invitedProperty());
        invited.setCellFactory(CheckBoxTableCell.forTableColumn(invited));
        table.getColumns().add(invited);

        TableColumn<Person, String> email = new TableColumn<>("Email");
        email.setCellValueFactory(cd -> cd.getValue().emailProperty());
        email.setCellFactory(TextFieldTableCell.forTableColumn());
        email.setOnEditCommit(t -> t.getRowValue().emailProperty().set(t.getNewValue()));
        table.getColumns().add(email);

        model.addListener(createListener(status));
        table.setEditable(true);
        table.setTableMenuButtonVisible(true);

        final VBox vbox = new VBox();
        vbox.setSpacing(8);
        vbox.setPadding(new Insets(8));
        vbox.getChildren().addAll(label, table, status);

        stage.setScene(new Scene(vbox));
        stage.show();
    }

    private String calcuateStatus() {
        int sum = 0;
        for (Person p : model) {
            if (p.invited.get()) {
                sum  = 1;
            }
        }
        return sum   " / "   model.size()   " invited.";
    }

    private ListChangeListener<Person> createListener(Label status) {
        return (Change<? extends Person> c) -> {
            while (c.next()) {
                status.setText(calcuateStatus());
            }
        };
    }

    private static class Person {

        private final StringProperty firstName;
        private final StringProperty lastName;
        private final BooleanProperty invited;
        private final StringProperty email;

        private Person(String fName, String lName, boolean invited, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.invited = new SimpleBooleanProperty(invited);
            this.email = new SimpleStringProperty(email);
        }

        public StringProperty firstNameProperty() {
            return firstName;
        }

        public StringProperty lastNameProperty() {
            return lastName;
        }

        public BooleanProperty invitedProperty() {
            return invited;
        }

        public StringProperty emailProperty() {
            return email;
        }

        public Observable[] extract() {
            return new Observable[]{invited};
        }
    }
}
  • Related