当前位置: 首页 > 知识库问答 >
问题:

向现有TableView添加复选框列

田意致
2023-03-14

我最近想在现有的tableView中添加一个复选框列。为了独立地研究这个问题,我从示例13-6开始创建一个表并向其中添加数据。我向Person模型类添加了BooleanProperty和访问器,并添加了一个新的TableColumn,其中包含一个CheckBoxTableCell作为单元工厂。如图所示,我在每一行上都看到一个复选框。尽管所有值都true,但没有选中;这些复选框是活动的,但是从不调用setactive()。最近关于这个话题的问题表明我遗漏了一些东西;我欢迎任何见解。

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);
        }
    }
}

共有1个答案

朱通
2023-03-14

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

  • 验证数据模型是否正确导出属性,如下所示。
  • 严格检查用显式的回调函数替换PropertyValueFactory的价值,如这里、这里和这里所述。

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

active.setCellFactory(CheckBoxTableCell.forTableColumn(active));
active.setCellFactory(CheckBoxTableCell.forTableColumn(
    (Integer i) -> data.get(i).active));

通过此更改,PropertyValueFactory可以找到新添加的BooleanProperty,并且FortableColumn()的原始形式仍然有效。请注意,PropertyValueFactory的便利性带来了一些限制。特别是,工厂对以前丢失的属性访问器的支持没有被注意到。幸运的是,相同的访问器允许用简单的回调替换每个列的值工厂。如下所示,不是PropertyValueFactory

active.setCellValueFactory(new PropertyValueFactory<>("active"));

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

active.setCellValueFactory(cd -> cd.getValue().activeProperty());

还要注意,person现在可以是private。此外,使用显式类型参数可以在编译期间进行更强的类型检查。

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;
        }
    }
}
 类似资料:
  • 我需要做的是-添加/删除数组中每个复选框的名称(由用户选中/未选中),并发送到服务器。我被困在以下代码中。任何帮助都很感激。谢啦 复选框项目。js

  • 我对JavaFX还很陌生。我已经无望地试图让它工作了这么长时间,但不知道为什么它不起作用。项不显示在TableView上。我使用scene Builder创建了UI。我看过很多类似的问题,似乎没有什么帮助。 简化为最小代码: 主: 控制器: Person类: FXML: 多谢了。

  • 我的网站遇到了一些问题。我想添加CSS到我的按钮像这样的东西,我发现在网上。https://codepen.io/allthingssmitty/pen/wjzvjo我无法为它添加ID,因为我无法更改HTML代码,因为它是由WordPress自动生成的。如有任何帮助,我们将不胜感激。

  • 我已经用FXML定义了一个tableview。它类似于以下内容: Action列将在每一行中包含带有文本“Delete”的按钮。我有两个问题: 如何将此删除按钮添加到JavaFX中的每一行最后一个单元格? 如何获取已单击“删除”按钮的行的索引?(以便删除该行或进行其他事件处理工作)

  • 问题内容: 我需要将表的主键更改为标识列,并且表中已经有许多行。 我有一个脚本来清理ID,以确保它们从1开始是连续的,在我的测试数据库上可以正常工作。 将列更改为具有标识属性的SQL命令是什么? 问题答案: 您无法更改现有的标识列。 您有2种选择, 创建一个具有标识的新表并删除现有表 创建一个具有标识的新列并删除现有列 方法1.( 新表 )在这里,您可以将现有数据值保留在新创建的标识列上。请注意,

  • 我有一个工作的Java项目,它使用Access.accdb数据库存储数据。我正在为我的程序进行更新,为用户提供更多的功能。为了使其工作,我需要在现有的表中添加一个列,该列填充了数据。当我研究时,我发现UCanAccess不能支持 这是不幸的,但我明白,由于低级别的驱动程序不支持它,UCanAccess也不能支持它。 然后我找到了这个解决办法: 如何使用UCanAccess修改表 但这对我也不起作用