JAVAFX - 隐藏列的神秘解决方案

JAVAFX - The hidden column's mysterious solution

我有一个 TableView,它显示来自 Derby table 的所有数据,除了项目的 "ID"(我不想让用户看到它。)

方法很简单,我对select所有属性做了一个SQL声明,但我没有要求ID列。我取回了一个 TableData,这个变量显示在 TableView 中,其中包含所有记录(这是一个简单的名单)。

我想允许用户从 table 中删除 "delete button"。

所以首先,当我们收集 ACTUAL selected 行的(如果不为空)ID 时,应该有一个 "OnAction" 方法(当用户单击删除按钮时),然后我们发送向数据库删除它的语句,其中 selected 项的(隐藏)ID 可以在 derby table 中找到。

因为它是一个 Namelist,并且 用户可以使用完全相同的数据创建另一条记录,在 table 视图中,记录可以是克隆的,没有差异。 (只有 ID 是唯一的,但是 table 视图不包含 id-s,所以很难)。

那么我们如何在不知道 ID 的情况下删除 selected 行呢?或者在table中没有显示ID,我们怎么知道呢? (搜索名称无效,因为可以有多个同名记录)

什么是"hidden column's mysterious solution"? :)

你的问题有一个简单的解决方案。如果您不想在 tableview 上显示 ID,则不必。 TableView 与您的 class 绑定,在您的情况下 user,而不是其字段。当您将值添加到表视图时,您可以控制要在其上显示的字段。无论您是否在 tableview 上显示它,您仍然拥有完整的用户对象(它仍然具有 ID)。

现在,有多种方法可以做到这一点。一种方法是 bind the id 与要在每一行中显示的 delete button 。每当 按下 删除按钮时, 从数据库中删除项目并将其从表视图中删除

我已经创建了一个工作示例来展示它是如何工作的。我硬编码了我的值,而不是从数据库中删除它,而是在控制台上打印 ID 值。

在这个例子中,Personclass可以被认为等同于你的user,每个都有一个id和其他属性.

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class TableViewSample extends Application {

    private TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data =
            FXCollections.observableArrayList(
                    new Person(10, "Jacob", "Smith", "jacob.smith@example.com"),
                    new Person(20, "Isabella", "Johnson", "isabella.johnson@example.com"),
                    new Person(30, "Ethan", "Williams", "ethan.williams@example.com"),
                    new Person(40, "Emma", "Jones", "emma.jones@example.com"),
                    new Person(50, "Michael", "Brown", "michael.brown@example.com")
            );

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

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(600);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));


        TableColumn deleteCol = new TableColumn("Delete");
        deleteCol.setMinWidth(100);
        deleteCol.setCellFactory(param -> new ButtonCell());
        deleteCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("id"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol, deleteCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }

    public static class Person {

        private final SimpleIntegerProperty id;
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(Integer id, String fName, String lName, String email) {
            this.id = new SimpleIntegerProperty(id);
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public int getId() {
            return id.get();
        }

        public void setId(int id) {
            this.id.set(id);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }

    private class ButtonCell extends TableCell<Person, Integer> {
        Image buttonDeleteImage = new Image("https://cdn1.iconfinder.com/data/icons/nuove/22x22/actions/fileclose.png");

        final Button cellDeleteButton = new Button("", new ImageView(buttonDeleteImage));

        ButtonCell() {
            cellDeleteButton.setOnAction(actionEvent -> {
                System.out.println("Deleted Id : " + getItem());// Make a DB call and delete the person with ID
                getTableView().getItems().remove(getIndex());
            });
        }

        @Override
        protected void updateItem(Integer t, boolean empty) {
            super.updateItem(t, empty);
            if (!empty) {
                setGraphic(cellDeleteButton);
            } else {
                setGraphic(null);
            }
        }
    }
}

不绑定ID就搞定

你需要:

deleteCol.setCellValueFactory(p -> {
        return new ReadOnlyObjectWrapper<Person>((Person)p.getValue());
});

自定义 ButtonCell 应该扩展 TableCell<Person, Person>

删除项目的逻辑变为:

System.out.println("Deleted ID : " +
                        getItem().getId());// Make a DB call and delete the person with ID
getTableView().getItems().remove(getIndex());

完整示例:

public class TableViewSample extends Application {

    private TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data =
            FXCollections.observableArrayList(
                    new Person(10, "Jacob", "Smith", "jacob.smith@example.com"),
                    new Person(20, "Isabella", "Johnson", "isabella.johnson@example.com"),
                    new Person(30, "Ethan", "Williams", "ethan.williams@example.com"),
                    new Person(40, "Emma", "Jones", "emma.jones@example.com"),
                    new Person(50, "Michael", "Brown", "michael.brown@example.com")
            );

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

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(600);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));


        TableColumn deleteCol = new TableColumn("Delete");
        deleteCol.setMinWidth(100);
        deleteCol.setCellFactory(param -> new ButtonCell());
        deleteCol.setCellValueFactory(p -> {
            return new ReadOnlyObjectWrapper<Person>((Person)p.getValue());
        });

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol, deleteCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }

    public static class Person {

        private final SimpleIntegerProperty id;
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(Integer id, String fName, String lName, String email) {
            this.id = new SimpleIntegerProperty(id);
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public int getId() {
            return id.get();
        }

        public void setId(int id) {
            this.id.set(id);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }

    private class ButtonCell extends TableCell<Person, Person> {
        Image buttonDeleteImage = new Image("https://cdn1.iconfinder.com/data/icons/nuove/22x22/actions/fileclose.png");

        final Button cellDeleteButton = new Button("", new ImageView(buttonDeleteImage));

        ButtonCell() {
            cellDeleteButton.setOnAction(actionEvent -> {
                System.out.println("Deleted ID : " +
                        getItem().getId());// Make a DB call and delete the person with ID
                getTableView().getItems().remove(getIndex());
            });
        }

        @Override
        protected void updateItem(Person t, boolean empty) {
            super.updateItem(t, empty);
            if (!empty) {
                setGraphic(cellDeleteButton);
            } else {
                setGraphic(null);
            }
        }
    }
}

我找到了一种更简单的方法,用户可以列出任何内容,然后由他决定显示什么和隐藏什么。如果我们不知道会收到什么数据,此解决方案也适用,但我们确信这将是我们不想显示的 "ID" 列:

        if (*ColumNameWeWantToHide*.equals(String.valueOf(columnName))) {
            col.prefWidthProperty().bind(*TableViewName*.widthProperty().divide(100));
        } 

它使我们也能够简单地使用 ID 号,而且如果我们愿意,我们也可以查看 ID,但默认情况下我们看不到它们。这是可用性和易于编码的良好结合。