(翻译)第十九回 JavaFX2.0 表格框TableView

小编 2026-06-07 阅读:1244 评论:0
  原文地址http://download.oracle.com/javafx/2.0/...

 

 

原文地址http://download.oracle.com/javafx/2.0/ui_controls/table-view.htm

 

 

JavaFX SDK API在的好几个类都被设计来以表格形式呈现数据。在 JavaFX应用中创建表格的最重要类是TableView , TableColumn , 和TableCell 。可以通过实现数据模型或者应用一个细胞工厂来产生表格。

表格的类提供了内置的功能来在必要的时候进行数据排序和重置大小。

Figure 13-1 是一个典型的表格,用来呈现地址簿中的联系人信息。

创建Table

 Example 13-1 中的代码块创建了一个空表格,它带有3列。然后被加入了应用的场景中。

 

Example 13-1 Adding a Table

import javafx.application.Application;import javafx.geometry.Insets;import javafx.scene.Group;import javafx.scene.Scene;import javafx.scene.control.Label;import javafx.scene.control.TableColumn;import javafx.scene.control.TableView;import javafx.scene.layout.VBox;import javafx.scene.text.Font;import javafx.stage.Stage; public class Main extends Application {        private TableView table = new TableView();            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(400);        stage.setHeight(500);         final Label label = new Label("Address Book");        label.setFont(new Font("Arial", 20));         TableColumn firstNameCol = new TableColumn("First Name");        TableColumn lastNameCol = new TableColumn("Last Name");        TableColumn emailCol = new TableColumn("Email");                  table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);               final VBox vbox = new VBox();        vbox.setSpacing(5);        vbox.getChildren().addAll(label, table);        vbox.setPadding(new Insets(10, 0, 0, 10));         ((Group) scene.getRoot()).getChildren().addAll(vbox);         stage.setScene(scene);        stage.show();    }}

 

表格控件是通过实例化TableView 类创建的。在 Example 13-1 中,它被加入到了VBox 布局容器中,然而,你可以直接把它加入应用场景中。

Example 13-1 定义了三列来存储地址簿中的以下信息:某个联系人的名和姓还有电邮地址。列是用TableColumn 类创建的。

TableView 类的getColumns 方法把前面创建的列加入到表格中。在应用中,可以用这个方法动态的添加和移除列。

编译运行的效果如下Figure 13-2 .

Figure 13-2 Table Without Data

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-2 Table Without Data"

可以通过调用setVisible 方法来管理列的可视性。比如说,你应用的逻辑要求隐藏用户电邮地址,可以这样达到目的:emailCol.setVisible(false) .

如果数据要求更复杂的数据呈现结构,可以创建内嵌的列。

比如,如果地址簿中的联系人有两个email账户,就需要两列来展示首选和次要地址了。创建两个子列,然后在emailCol 上调用getColumns 方法,见 Example 13-2 .

Example 13-2 Creating Nested Columns

TableColumn firstEmailCol = new TableColumn("Primary");TableColumn secondEmailCol = new TableColumn("Secondary");emailCol.getColumns().addAll(firstEmailCol, secondEmailCol);

把这些代码加入到 Example 13-1 , 然后编译运行,表格的呈现效果如 Figure 13-3 .

Figure 13-3 Table with Nested Columns

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-3 Table with Nested Columns"

尽管表格被加入到了应用中,标准标题依然显示的是"No content in table" 因为没定义数据。为了不显示这个标题,可以使用setPlaceholder方法指定一个 Node 对象来显示在空表格中。

定义Data Model

当在JavaFX应用中创建表格时,最佳实践是实现一个定义了数据模型、提供了方法和字段的类来扩展表格的工作。Example 13-3 创建了一个Person类来定义地址簿中的数据。

Example 13-3 Creating the Person Class

public static class Person {    private final SimpleStringProperty firstName;    private final SimpleStringProperty lastName;    private final SimpleStringProperty email;     private Person(String fName, String lName, String email) {        this.firstName = new SimpleStringProperty(fName);        this.lastName = new SimpleStringProperty(lName);        this.email = new SimpleStringProperty(email);    }     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);    }        }

firstName , lastName , 和email 字符串属性(string property)是创建来引用特定的数据元素的。

另外, get和 set方法是提供给每个数据元素的。这样,比如说, getFirstName方法返回了 firstName属性的值,而 setFirstName 方法为这个属性指定了值。

当数据模型在 Person 类中形成时,可以创建一个ObservableList 数组来定义足够多的行来在表格中显示你的数据。看Example 13-4 中的代码。

 

Example 13-4 Defining Table Data in an Observable List

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

 

下一步是将数据和表格列相关联。可以通过为每个数据元素定义的属性来实现,见Example 13-5 .

Example 13-5 Setting Data Properties to Columns

firstNameCol.setCellValueFactory(    new PropertyValueFactory<Person,String>("firstName"));lastNameCol.setCellValueFactory(    new PropertyValueFactory<Person,String>("lastName"));emailCol.setCellValueFactory(    new PropertyValueFactory<Person,String>("email"));

setCellValueFactory 方法为每列指定了一个细胞工厂。细胞工厂是通过使用PropertyValueFactory 类来实现的,该类使用了表格列的firstName , lastName 和email 属性来引用Person相应的方法。

定义了数据模型、加入数据并和列相关联后可以把数据加入表格了。使用TableView 类的setItems 方法:table.setItems(data) .

由于ObservableList对象可以跟踪元素的任何改变, TableView的内容在数据改变后是自动更新的。

查看 Example 13-6 中的代码。

Example 13-6 Creating a Table and Adding Data to It

import javafx.beans.property.SimpleStringProperty;import javafx.scene.control.cell.PropertyValueFactory;import javafx.application.Application;import javafx.collections.FXCollections;import javafx.collections.ObservableList;import javafx.geometry.Insets;import javafx.scene.Group;import javafx.scene.Scene;import javafx.scene.control.Label;import javafx.scene.control.TableColumn;import javafx.scene.control.TableView;import javafx.scene.layout.VBox;import javafx.scene.text.Font;import javafx.stage.Stage; public class Main extends Application {     public static class Person {        private final SimpleStringProperty firstName;        private final SimpleStringProperty lastName;        private final SimpleStringProperty email;         private Person(String fName, String lName, String email) {            this.firstName = new SimpleStringProperty(fName);            this.lastName = new SimpleStringProperty(lName);            this.email = new SimpleStringProperty(email);        }         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 TableView<Person> table = new TableView<Person>();    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) {        Scene scene = new Scene(new Group());        stage.setTitle("Table View Sample");        stage.setWidth(400);        stage.setHeight(500);         final Label label = new Label("Address Book");        label.setFont(new Font("Arial", 20));         TableColumn firstNameCol = new TableColumn("First Name");        firstNameCol.setCellValueFactory(            new PropertyValueFactory<Person,String>("firstName")        );         TableColumn lastNameCol = new TableColumn("Last Name");        lastNameCol.setCellValueFactory(            new PropertyValueFactory<Person,String>("lastName")        );         TableColumn emailCol = new TableColumn("Email");        emailCol.setMinWidth(200);        emailCol.setCellValueFactory(            new PropertyValueFactory<Person,String>("email")        );         table.setItems(data);        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);         final VBox vbox = new VBox();        vbox.setSpacing(5);        vbox.getChildren().addAll(label, table);        vbox.setPadding(new Insets(10, 0, 0, 10));         ((Group) scene.getRoot()).getChildren().addAll(vbox);         stage.setScene(scene);        stage.show();    }}

编译运行的效果如图 Figure 13-4 所示。

Figure 13-4 Table Populated with Data

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-4 Table Populated with Data"

新增行

 Figure 13-4 中的表格包含了5行,目前还无法更改。

可以使用文本框来输入First Name, Last Name和 Email 列中的内容。Text Field控件使你的应用能够接收用户的输入。Example 13-7创建了三个文本框并分别定义了提示语,还创建了一个Add按钮。

 

Example 13-7 Using Text Fields to Enter New Items in the Table

final TextField addFirstName = new TextField();addFirstName.setPromptText("Last Name");addFirstName.setMaxWidth(firstNameCol.getPrefWidth());final TextField addLastName = new TextField();addLastName.setMaxWidth(lastNameCol.getPrefWidth());addLastName.setPromptText("Last Name");final TextField addEmail = new TextField();addEmail.setMaxWidth(emailCol.getPrefWidth());addEmail.setPromptText("Email"); final Button addButton = new Button("Add");addButton.setOnAction(new EventHandler<ActionEvent>() {    @Override public void handle(ActionEvent e) {        data.add(new Person(            addFirstName.getText(),            addLastName.getText(),            addEmail.getText()        ));        addFirstName.setText("");        addLastName.setText("");        addEmail.setText("");    }});

 

点击 Add按钮后,文本框中的值就包含进一个Person 的构造方法并加入到data可见列表( observable list)中。这样 ,新输入的联系人信息就显示在表格中了。

查看 Example 13-8 中的代码。

Example 13-8 Table with the Text Fields to Enter New Items

import javafx.application.Application;import javafx.beans.property.SimpleStringProperty;import javafx.beans.property.StringProperty;import javafx.collections.FXCollections;import javafx.collections.ObservableList;import javafx.event.ActionEvent;import javafx.event.EventHandler;import javafx.geometry.Insets;import javafx.scene.Group;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.PropertyValueFactory;import javafx.scene.layout.HBox;import javafx.scene.layout.VBox;import javafx.scene.text.Font;import javafx.stage.Stage; public class Main extends Application {     public static class Person {         private final StringProperty firstName;        private final StringProperty lastName;        private final StringProperty email;         private Person(String fName, String lName, String email) {            this.firstName = new SimpleStringProperty(fName);            this.lastName = new SimpleStringProperty(lName);            this.email = new SimpleStringProperty(email);        }         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 TableView<Person> table = new TableView<Person>();    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")        );     private HBox hb = new HBox();     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(400);        stage.setHeight(500);         final Label label = new Label("Address Book");        label.setFont(new Font("Arial", 20));         TableColumn firstNameCol = new TableColumn("First");        firstNameCol.setCellValueFactory(            new PropertyValueFactory<Person,String>("firstName")        );         TableColumn lastNameCol = new TableColumn("Last");        lastNameCol.setCellValueFactory(            new PropertyValueFactory<Person,String>("lastName")        );         TableColumn emailCol = new TableColumn("Email");        emailCol.setMinWidth(200);        emailCol.setCellValueFactory(                new PropertyValueFactory<Person,String>("email")        );         table.setItems(data);        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);         final TextField addFirstName = new TextField();        addFirstName.setPromptText("Last Name");        addFirstName.setMaxWidth(firstNameCol.getPrefWidth());        final TextField addLastName = new TextField();        addLastName.setMaxWidth(lastNameCol.getPrefWidth());        addLastName.setPromptText("Last Name");        final TextField addEmail = new TextField();        addEmail.setMaxWidth(emailCol.getPrefWidth());        addEmail.setPromptText("Email");         final Button addButton = new Button("Add");        addButton.setOnAction(new EventHandler<ActionEvent>() {            @Override public void handle(ActionEvent e) {                data.add(new Person(                        addFirstName.getText(),                        addLastName.getText(),                        addEmail.getText()                        ));                addFirstName.setText("");                addLastName.setText("");                addEmail.setText("");            }        });         hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);        hb.setSpacing(3);         final VBox vbox = new VBox();        vbox.setSpacing(5);        vbox.getChildren().addAll(label, table, hb);        vbox.setPadding(new Insets(10, 0, 0, 10));         ((Group) scene.getRoot()).getChildren().addAll(vbox);         stage.setScene(scene);        stage.show();    }}

应用并没有提供任何过滤器来检查输入(比如输入的电邮地址并不符合正确形式)。 你可以在开发的时候自己加上这些功能。

当前应用也不能检查十分输入了空值。如果没输入内容,点击Add按钮会加入空行。

Figure 13-5 演示了用户如何新增行。

 

Figure 13-5 Adding Contact Information to the Address Book

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-5 Adding Contact Information to the Address Book"

 

Figure 13-6 是上图点击Add按钮后的效果。联系人Emma White的信息现在在表格中显示了。

数据排序

TableView 类提供了内置的数据排序能力。。用户可以点击列标题来改变数据顺序。点击一次是递增排序,点击两次是递减排序,点击三次是不能排序。默认地,是没有排序。

用户可以万恶表格中的多个列进行排序,并在排序操作中指定各列的优先级。要排序多列,在点击列标题的时候按住Shift键即可。

Figure 13-7 中,第一列应用了升序,第二列是降序。注意第一列的优先级要高于第二列。

 

Figure 13-7 Sorting Multiple Columns

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-7 Sorting Multiple Columns"

 

作为开发者,可以通过 setSortType方法为应用中的每一列设置排序参数。 可以指定是升序还是降序。比如,下面这行代码设置了emailCol列是降序排序:emailCol.setSortType(TableColumn.SortType.DESCENDING);

可以通过从 TableView.sortOrder可见列表增加或删除 TableColumn实例来指定要排序哪些列。该列表中列的顺序就是排序的优先级 (比如,0项目的优先级高于第一个项目。)

使用setSortable(false)方法可以阻止列的排序。

编辑Table中的数据

TableView类不仅显示表格数据,也提供了编辑数据的功能。可以使用 TableView.edit(int row, TableColumn<S,?> column) 方法开始编辑。也可以使用TableCell类的方法编辑表格数据。见 Example 13-9 .

Example 13-9 Implementing Cell Editing

class EditingCell extends TableCell<Person, String> {              private TextField textField;         public EditingCell() {                    }         @Override         public void startEdit() {            super.startEdit();            if (isEmpty()) {                return;            }             if (textField == null) {                createTextField();            } else {                textField.setText(getItem());            }            setGraphic(textField);            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);        }         @Override        public void cancelEdit() {            super.cancelEdit();            setContentDisplay(ContentDisplay.TEXT_ONLY);        }         @Override                 public void updateItem(String item, boolean empty) {            super.updateItem(item, empty);            if (!isEmpty()) {                if (textField != null) {                    textField.setText(item);                }                setText(item);            }        }         private void createTextField() {            textField = new TextField(getItem());            textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);            textField.setOnKeyReleased(new EventHandler<KeyEvent>() {                @Override public void handle(KeyEvent t) {                    if (t.getCode() == KeyCode.ENTER) {                        commitEdit(textField.getText());                    } else if (t.getCode() == KeyCode.ESCAPE) {                        cancelEdit();                    }                }            });        }    }

Example 13-9,createTextField方法使用了 textField变量来分析输入串并调用 commitEdit或 cancelEdit 方法(取决于按下了 Enter还是Escape键)

setCellFactory 方法能用来建立定制的细胞工厂。定制细胞工厂的首要任务是无论何时请求多返回一个新建的TableCell实例。 Example 13-10 展示了如何为firstNameCol , lastNameColemailCol列实现细胞工厂。

 

Example 13-10 Using a Cell Factory

Callback<TableColumn, TableCell> cellFactory =     new Callback<TableColumn, TableCell>() {        public TableCell call(TableColumn p) {            return new EditingCell();    }};firstNameCol.setCellFactory(cellFactory);lastNameCol.setCellFactory(cellFactory);emailCol.setCellFactory(cellFactory);

 

setOnEditCommit方法,如 Example 13-11 所示,这样表格能处理项目的任何改变。该方法标识了一个编辑过的项目,取回了新数据,代替了data 可见列表的相应数据。

 

Example 13-11 Processing Edited Data in the Table

//Enabling editingtable.setEditable(true);//Modifying the firstName propertyfirstNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {    @Override public void handle(CellEditEvent<Person, String> t) {        ((Person)t.getTableView().getItems().get(            t.getTablePosition().getRow())).setFirstName(t.getNewValue());    }});//Modifying the lastName propertylastNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {    @Override public void handle(CellEditEvent<Person, String> t) {        ((Person)t.getTableView().getItems().get(            t.getTablePosition().getRow())).setLastName(t.getNewValue());    }}); //Modifying the email propertyemailCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {    @Override public void handle(CellEditEvent<Person, String> t) {        ((Person)t.getTableView().getItems().get(            t.getTablePosition().getRow())).setEmail(t.getNewValue());     }});

 

在 Figure 13-8中,用户编辑了Michael Brown的姓,输入了新值并按了回车。回车后就不能再编辑了,这种行为由TextField类的实现决定。

Figure 13-8 Editing a Table Cell

(翻译)第十九回 JavaFX2.0 表格框TableView
Description of "Figure 13-8 Editing a Table Cell"

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表