首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将CheckBox列添加到现有的TableView中

将CheckBox列添加到现有的TableView中
EN

Stack Overflow用户
提问于 2021-08-29 01:28:02
回答 1查看 387关注 0票数 2

最近,我想将CheckBox列添加到现有的TableView中。为了孤立地研究这个问题,我从https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm#JFXUI271开始。我向Person模型类添加了一个Person和访问器,并添加了一个以CheckBoxTableCell作为单元工厂的新TableColumn。如图所示,我在每一行上都看到一个CheckBox。虽然所有的值都是true,但没有一个被选中;复选框是活动的,但从未调用setActive()。最近关于这个主题的问题表明,我遗漏了一些东西;我欢迎您的任何见解。

代码语言:javascript
复制
import javafx.application.Application;
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.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.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

/**
 * Example 13-6 Creating a Table and Adding Data to It
 * https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm#CJAGAAEE
 */
public class TableViewSample extends Application {

    private final TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data
        = FXCollections.observableArrayList(
            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")
        );

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

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

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

        table.setEditable(true);

        TableColumn<Person, Boolean> active = new TableColumn<>("Active");
        active.setCellValueFactory(new PropertyValueFactory<>("active"));
        active.setCellFactory(CheckBoxTableCell.forTableColumn(active));

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

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

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

        table.setItems(data);
        table.getColumns().addAll(active, firstName, lastName, email);

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

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

    public static class Person {

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

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

        public boolean getActive() {
            return active.get();
        }

        public void setActive(boolean b) {
            active.set(b);
        }

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

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

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

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

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

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-29 01:28:02

摘要:正如注意到的这里,这很可能是一个错误;避免陷阱的步骤包括:

  • 验证数据模型是否正确地导出属性,如这里所示。
  • 在可能的情况下,严格检查用显式PropertyValueFactory替换Callback的价值,如概述的这里这里这里这里这里

问题是,CheckBoxTableCell无法根据提供的参数查找或绑定ObservableProperty<Boolean>

代码语言:javascript
复制
active.setCellFactory(CheckBoxTableCell.forTableColumn(active));

CheckBoxTableCell提交给表列以访问目标Boolean属性。要查看效果,请将active参数替换为显式返回行iObservableValue<Boolean>Callback

代码语言:javascript
复制
active.setCellFactory(CheckBoxTableCell.forTableColumn(
    (Integer i) -> data.get(i).active));

虽然这使复选框正常工作,但根本的问题是Person类需要active属性的访问器。https://docs.oracle.com/javase/8/javafx/properties-binding-tutorial/binding.htm#JFXBD111讨论了属性方法命名约定,tablecellfactoryPerson类为每个属性演示了一个带有属性getter的工作模型类,如下所示。

通过这种更改,PropertyValueFactory可以找到新添加的BooleanProperty,并且forTableColumn()的原始形式可以工作。请注意,PropertyValueFactory的便利性伴随着一些局限性。特别是,工厂对以前丢失的属性访问器的失败支持没有引起注意。幸运的是,相同的访问器允许为每个列的值工厂替换一个简单的Callback。如这里所示,而不是PropertyValueFactory

代码语言:javascript
复制
active.setCellValueFactory(new PropertyValueFactory<>("active"));

传递一个返回相应属性的lamda表达

代码语言:javascript
复制
active.setCellValueFactory(cd -> cd.getValue().activeProperty());

还请注意,Person现在可以是private。此外,显式类型参数的使用在编译期间提供了更强的类型检查。

代码语言:javascript
复制
import javafx.application.Application;
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.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.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

/**
 * https://stackoverflow.com/a/68969223/230513
 */
public class TableViewSample extends Application {

    private final TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data
        = FXCollections.observableArrayList(
            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")
        );

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

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

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

        table.setEditable(true);

        TableColumn<Person, Boolean> active = new TableColumn<>("Active");
        active.setCellValueFactory(cd -> cd.getValue().activeProperty());
        active.setCellFactory(CheckBoxTableCell.forTableColumn(active));

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

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

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

        table.setItems(data);
        table.getColumns().addAll(active, firstName, lastName, email);

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

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

    private static class Person {

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

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

        public BooleanProperty activeProperty() {
            return active;
        }

        public StringProperty firstNameProperty() {
            return firstName;
        }

        public StringProperty lastNameProperty() {
            return lastName;
        }

        public StringProperty emailProperty() {
            return email;
        }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68969222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档