JavaFX中TableView的使用

稍微说说JavaFX里面TableView怎么用,(其实在JavaFX的源码中都有示例。。。)

首先要了解TableView是用来做什么的,TableView是JavaFX的一个表视图,用来显示表格的,在TableView的类注释中写了

/**
 * @see TableColumn
 * @see TablePosition
 * @param <S> The type of the objects contains within the TableView items list
 * @since JavaFX 2.0
 */

然后看一下官方给出的示例是啥样的

Creating a TableView
Creating a TableView is a multi-step process, and also depends on the underlying data model needing to be represented. For this example we'll use an ObservableList<Person>, as it is the simplest way of showing data in a TableView. The Person class will consist of a first name and last name properties. That is:

  public class Person {
     private StringProperty firstName;
     public void setFirstName(String value) { firstNameProperty().set(value); }
     public String getFirstName() { return firstNameProperty().get(); }
     public StringProperty firstNameProperty() {
         if (firstName == null) firstName = new SimpleStringProperty(this, "firstName");
         return firstName;
     }

     private StringProperty lastName;
     public void setLastName(String value) { lastNameProperty().set(value); }
     public String getLastName() { return lastNameProperty().get(); }
     public StringProperty lastNameProperty() {
         if (lastName == null) lastName = new SimpleStringProperty(this, "lastName");
         return lastName;
     }

     public Person(String firstName, String lastName) {
         setFirstName(firstName);
         setLastName(lastName);
     }
 }

The data we will use for this example is:

  List<Person> members = List.of(
     new Person("William", "Reed"),
     new Person("James", "Michaelson"),
     new Person("Julius", "Dean"));

Firstly, we need to create a data model. As mentioned, for this example, we'll be using an ObservableList<Person>:

  ObservableList<Person> teamMembers = FXCollections.observableArrayList(members);

Then we create a TableView instance:

  TableView<Person> table = new TableView<>();
  table.setItems(teamMembers);

With the items set as such, TableView will automatically update whenever the teamMembers list changes. If the items list is available before the TableView is instantiated, it is possible to pass it directly into the constructor:

  TableView<Person> table = new TableView<>(teamMembers);

At this point we now have a TableView hooked up to observe the teamMembers observableList. The missing ingredient now is the means of splitting out the data contained within the model and representing it in one or more TableColumn instances. To create a two-column TableView to show the firstName and lastName properties, we extend the last code sample as follows:

  TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
 firstNameCol.setCellValueFactory(new PropertyValueFactory<>(members.get(0).firstNameProperty().getName())));
 TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
 lastNameCol.setCellValueFactory(new PropertyValueFactory<>(members.get(0).lastNameProperty().getName())));

 table.getColumns().setAll(firstNameCol, lastNameCol);

说TableView<S>这个泛型代表的是table中每一列所存储的对象类型

就是说每一行作为一个对象,每一列是代表该对象所具有的属性,在给TableView初始化之后,要向TableView添加不同的列,添加TableColumn

然后就发现TableColumn<S, T>这个类有两个泛型,这个第一个S代表的就是和TableView一样的,这个T就是Type,代表该列所表示的数据类型。话不多说,上代码

/**
 * 先创建一个静态内部类
 * 作为TableView的行数据
 */
public static class Person {
    private final StringProperty name;
    private final IntegerProperty age;
    private final StringProperty sex;
    private final StringProperty email;

    public Person(String name, int age, String sex, String email) {
        this.name = new SimpleStringProperty(name);
        this.age = new SimpleIntegerProperty(age);
        this.sex = new SimpleStringProperty(sex);
        this.email = new SimpleStringProperty(email);
    }

    public int getAge() {
        return age.get();
    }

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

    public String getName() {
        return name.get();
    }

    public String getSex() {
        return sex.get();
    }
}

然后就初始化TableView

//这个data是数据源
TableView<Person> table = new TableView<>(data);
//在写的时候也可以先初始化然后再设置数据源
TableView<Person> table = new TableView<>();
table.setItems(data);
//table可以可以作为成员变量

然后我们需要设置一个数据源

private final ObservableList<Person> data = FXCollections.observableArrayList(
        new Person("张三", 10, "男", "123123@qq.com"),
        new Person("李四", 90, "女", "123321@qq.com"),
        new Person("王富贵", 80, "男", "321123@qq.com")
);

这个是一个集合,用了观察者模式

观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。

能够让表格实时监控数据的变化从而做出相应的改变

然后就是向表格中添加列

TableColumn<Person, String> nameCol = new TableColumn<>("姓名");
TableColumn<Person, String> ageCol = new TableColumn<>("年龄");
TableColumn<Person, String> sexCol = new TableColumn<>("性别");
TableColumn<Person, String> emailCol = new TableColumn<>("邮箱");

然后我们需要将列的对象和数据的属性进行绑定

nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));
emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));

这个参数一定要是前面People类中所具有的属性

然后将这些列数据添加到TableView中

table.getColumns().addAll(nameCol, ageCol, sexCol, emailCol);

我们来看一下总的代码

public class Main extends Application {
    private static final TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data = FXCollections.observableArrayList(
        new Person("张三", 10, "男", "123123@qq.com"),
        new Person("李四", 90, "女", "123321@qq.com"),
        new Person("王富贵", 80, "男", "321123@qq.com")
    );
    @Override
    public void start(Stage stage) {
        //创建根面板
        BorderPane root = new BorderPane();
        Scene scene = new Scene(root, 500, 500);
        //创建表格的列
        TableColumn<Person, String> nameCol = new TableColumn<>("姓名");
        TableColumn<Person, String> ageCol = new TableColumn<>("年龄");
        TableColumn<Person, String> sexCol = new TableColumn<>("性别");
        TableColumn<Person, String> emailCol = new TableColumn<>("邮箱");
        //将表格的列和类的属性进行绑定
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
        sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));
        emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));
        //设置可编辑
        table.setEditable(true);
        //将列添加到TableView中
        table.getColumns().addAll(nameCol, ageCol, sexCol, emailCol);
        //设置数据源
        table.setItems(data);
        //将表格添加至根面板
        root.setCenter(table);
        //为舞台设置场景
        stage.setScene(scene);
        //场景显示
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
    
    //内部类
    public static class Person {
        private final StringProperty name;
        private final IntegerProperty age;
        private final StringProperty sex;
        private final StringProperty email;

        public Person(String name, int age, String sex, String email) {
            this.name = new SimpleStringProperty(name);
            this.age = new SimpleIntegerProperty(age);
            this.sex = new SimpleStringProperty(sex);
            this.email = new SimpleStringProperty(email);
        }

        public int getAge() {
            return age.get();
        }

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

        public String getName() {
            return name.get();
        }

        public String getSex() {
            return sex.get();
        }
    }

}

结果图

 我们还可以设置列的属性能让表格可编辑(双击表格进入编辑状态)

nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
ageCol.setCellFactory(TextFieldTableCell.forTableColumn());
sexCol.setCellFactory(TextFieldTableCell.forTableColumn());
emailCol.setCellFactory(TextFieldTableCell.forTableColumn());

最后做个稍微高级一点的  美化一下

package testPack;

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Objects;

/**
 * @author BLLGDZ
 * @data 2022-02-22 
 * @time 16:32
 * @version java - 17.0.1
 * @product_name IntelliJ IDEA
 * @Association: DMU
 * @E-mail: 670855120@qq.com
 * Right to use this code in any way you want without
 * warranty, support or any guarantee of it working
 */
public class Main extends Application {
    private Scene scene = null;
    private final int WIDTH = 600;
    private final int HEIGTH = 600;
    private final Label label = new Label("TableViewTest");
    private final TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data = FXCollections.observableArrayList();
    private final Button btnAdd = new Button("添加");
    private final Button btnDel = new Button("删除");
    private final TextField txtName = new TextField();
    private final TextField txtAge = new TextField();
    private final TextField txtSex = new TextField();
    private final TextField txtEmail = new TextField();
    private final TextField txtPhone = new TextField();
    private final TextField txtQQ = new TextField();

    @Override
    public void start(Stage stage) {
        scene = new Scene(new BorderPane(), WIDTH, HEIGTH);
        initCSS();
        initComponents();
        initEvents();
        stage.setScene(scene);
        stage.show();
    }

    private void initComponents() {
        BorderPane root = (BorderPane) scene.getRoot();

        label.setPadding(new Insets(10, 0, 10, 0));

        //这个是我之前讲过的一种居中的方式 在前面的文章中有讲解,
        //利用HBox和VBox水平排列和垂直排列的特性将VBox和HBox相互嵌套能够打到居中的效果
        VBox vBox = new VBox();
        HBox hBox = new HBox();
        vBox.setAlignment(Pos.CENTER);
        hBox.setAlignment(Pos.CENTER);

        HBox inputBox = new HBox(10);
        inputBox.setAlignment(Pos.CENTER);
        inputBox.getChildren().addAll(txtName, txtAge, txtSex, txtEmail, txtPhone, txtQQ);
        inputBox.setPadding(new Insets(10, 10, 0, 10));

        HBox btnBox = new HBox(50);
        btnBox.setAlignment(Pos.CENTER);
        btnBox.getChildren().addAll(btnAdd, btnDel);
        btnBox.setPadding(new Insets(10, 10, 10, 10));

        txtAge.setTooltip(new Tooltip("填入年龄"));
        txtName.setTooltip(new Tooltip("填入姓名"));
        txtEmail.setTooltip(new Tooltip("填入邮箱"));
        txtSex.setTooltip(new Tooltip("填入性别"));
        txtPhone.setTooltip(new Tooltip("填入联系电话"));
        txtAge.setPromptText("年龄");
        txtName.setPromptText("姓名");
        txtEmail.setPromptText("Email");
        txtSex.setPromptText("性别");
        txtPhone.setPromptText("联系电话");
        txtQQ.setPromptText("QQ");

        TableColumn<Person, String> nameCol = new TableColumn<>("姓名");
        TableColumn<Person, Integer> ageCol = new TableColumn<>("年龄");
        TableColumn<Person, String> sexCol = new TableColumn<>("性别");
        TableColumn<Person, String> infoCol = new TableColumn<>("信息");
        TableColumn<Person, String> QQCol = new TableColumn<>("QQ");
        TableColumn<Person, String> phoneNumCol = new TableColumn<>("联系电话");

        nameCol.setMinWidth(100);
        ageCol.setMinWidth(100);
        sexCol.setMinWidth(100);
        QQCol.setMinWidth(130);
        phoneNumCol.setMinWidth(130);
        infoCol.getColumns().addAll(QQCol, phoneNumCol);

        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
        sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));
        QQCol.setCellValueFactory(new PropertyValueFactory<>("QQnum"));
        phoneNumCol.setCellValueFactory(new PropertyValueFactory<>("phoneNum"));

        table.setItems(data);
        table.getColumns().addAll(nameCol, ageCol, sexCol, infoCol);
        vBox.getChildren().addAll(label, table, inputBox, btnBox);

        hBox.getChildren().add(vBox);
        root.setCenter(hBox);
    }

    private void initEvents() {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        btnAdd.setOnAction(e -> {
            //验证表单(我就做个简单的验证非空了  剩下什么邮箱姓名电话格式这些东西,大家自己努力把 一堆正则表达式)
            if (txtName.getText().isEmpty()
                    || txtSex.getText().isEmpty()
                    || txtPhone.getText().isEmpty()
                    || txtEmail.getText().isEmpty()
                    || txtAge.getText().isEmpty()) {
                alert.setContentText("表格未填满!");
                alert.show();
                return;
            }
            data.add(
                    new Person(txtName.getText(), Integer.parseInt(txtAge.getText()), txtSex.getText(), txtEmail.getText(), txtQQ.getText(), txtPhone.getText())
            );
        });
        btnDel.setOnAction(e -> {
            if (data.size() == 0) {
                alert.setContentText("表格为空!");
                alert.show();
                return;
            }
            int moveIndex = table.getSelectionModel().getFocusedIndex();
            System.out.println(moveIndex);
            data.remove(moveIndex);
        });
    }

    private void initCSS() {
        BorderPane root = (BorderPane) scene.getRoot();
        //懒了  就这么写了
        String txt = """
                     -fx-background-radius: 20px;
                     -fx-background-color: rgba(0, 0, 0, .3);
                     -fx-text-fill: white;
                     -fx-pref-height: 25px;
                     """;
        String backgroundColor = """
                                 -fx-background-color: #91B493;
                                 """;
        String table_backgroundColor = """
                                       -fx-background-color: #4B4E2A;
                                       """;
        String label = """
                       -fx-font-size: 20px;
                       -fx-text-fill: white;
                       -fx-font-weight: bold;
                       """;
        String btn = """
                     -fx-background-color: #904840;
                     -fx-background-radius: 20px;
                     -fx-text-fill: white;
                     -fx-pref-width: 100px;
                     -fx-pref-height: 30px;
                     """;
        txtEmail.setStyle(txt);
        txtQQ.setStyle(txt);
        txtName.setStyle(txt);
        txtSex.setStyle(txt);
        txtPhone.setStyle(txt);
        txtAge.setStyle(txt);
        root.setStyle(backgroundColor);
        this.label.setStyle(label);
        btnDel.setStyle(btn);
        btnAdd.setStyle(btn);
        this.table.setStyle(table_backgroundColor);
    }

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

    public static class Person {
        private final StringProperty name;
        private final IntegerProperty age;
        private final StringProperty sex;
        private final StringProperty email;
        private final StringProperty QQnum;
        private final StringProperty phoneNum;

        public Person(String name, int age, String sex, String email, String QQnum, String phoneNum) {
            this.name = new SimpleStringProperty(name);
            this.age = new SimpleIntegerProperty(age);
            this.sex = new SimpleStringProperty(sex);
            this.email = new SimpleStringProperty(email);
            this.QQnum = new SimpleStringProperty(QQnum);
            this.phoneNum = new SimpleStringProperty(phoneNum);
        }


        public int getAge() {
            return age.get();
        }

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

        public String getName() {
            return name.get();
        }

        public String getSex() {
            return sex.get();
        }

        public String getPhoneNum() {
            return phoneNum.get();
        }

        public String getQQnum() {
            return QQnum.get();
        }
    }

}

效果图:(实属有点丑  但是还是对付看吧)

对了推荐大家一个选色的网址   这个NIPPON COLORS - 日本の伝統色可以在里面找喜欢的颜色

 看我这么可怜,给我点个赞吧

  • 42
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值