javafx之tableview

javafx之tableview

tableview是一个非常常用的显示模式,我们可以对其加以改造,这样以便适应更多不同的需求。同时,因为javafx可以使用css,这样我们对tableview的显示就更得心应手了。

一、 tableview创建及数据加载:

当然,这是已经加入数据的tablew,来源于oracle docs.oracle.com/javase/

import javafx.application.Application;
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.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
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) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        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<>("firstName"));
        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<>("lastName"));
        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<>("email"));
        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
        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 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);
} 

这段代码可以显示上图。

这里注意,bean中字段的类型是SimpleStringProperty,而不是普通的String。

显示控制文件中 firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));就是数据绑定,“firstName”对应你bean中创建的字段。

填充数据所用的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")
);

是javafx独特的ObservableList,如字面所述,是一个观察者的list,和ui绑定,一旦更改就直接改变ui,相当方便。当然,也要注意,不要对其进行频繁的操作,如果需要进行一些数据的调整,可以创建一个普通的arraylist,进行调整后,用ObservableList的addall方法加载。

二,tableview的标题头

如果想要取消的话:

 tableview.widthProperty().addListener(new ChangeListener<Number>() {
           @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                Pane header = (Pane) tableview.lookup("TableHeaderRow");
                if (header != null && header.isVisible()) {
                    header.setVisible(false);
                  //  header.setBackground(new Background(new BackgroundFill(Color.RED,CornerRadii.EMPTY,Insets.EMPTY)));
                    header.setManaged(false);
        });

想要更改显示字体,背景等均可以通过css实现,下面是我实现的一个实例:

.table-view .column-header .label{
-fx-text-fill:white;
-fx-font-weight:bold;
-fx-background-color:black;
-fx-font-size:24px;
-fx-alignment:baseline-left;
.table-view .column-header{
-fx-background-color:black;
-fx-label-paddding:-20,0,0,0;
-fx-pref-height:36px;
}

基本就是操作了标题头和标题头中的文字。

三,表格可编辑

首先调用tableview的setEditable(true),使其可编辑。然后有两种方式:

 Callback<TableColumn<Map, String>, TableCell<Map, String>>
            cellFactoryForMap = (TableColumn<Map, String> p) -> 
                new TextFieldTableCell(new StringConverter() {
                    @Override
                        public String toString(Object t) {
                        return t.toString();
                    @Override
                    public Object fromString(String string) {
                        return string;
        firstDataColumn.setCellFactory(cellFactoryForMap);

 firstDataColumn.setCellFactory(TextFieldTableCell.<>forTableColumn());

同样可以让表格可编辑。然后调用对象的setOnEditCommit方法处理编写后的处理,其中event.getnewvalue方法可以获得你输入的值。这里注意,javafx对tableview输入的默认方式是双击单元格可以输入,键盘回车键提交。


四、tableview中的cell

css:

.table-cell{
    -fx-padding: -6 0 0 0;

设定单元格覆盖:

 tableview.setFixedCellSize(35.0);

五、tableview拖拽

  private static final DataFormat SERIALIZED_MIME_TYPE = new DataFormat("application/x-java-serialized-object");
tableview.setRowFactory(tv1->{
              TableRow<T> row=new TableRow<>();
              row.setOnDragDetected(event -> {
                  if (! row.isEmpty()) {
                      Integer index = row.getIndex();
                      Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
                      db.setDragView(row.snapshot(null, null));
                      ClipboardContent cc = new ClipboardContent();
                      cc.put(SERIALIZED_MIME_TYPE, index);
                      db.setContent(cc);
                      event.consume();
              row.setOnDragOver(event -> {
                  Dragboard db = event.getDragboard();
                  if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                      if (row.getIndex() != ((Integer)db.getContent(SERIALIZED_MIME_TYPE)).intValue()) {
                          event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                          event.consume();
              row.setOnDragDropped(event -> {
                  Dragboard db = event.getDragboard();
                  if (db.hasContent(SERIALIZED_MIME_TYPE)) {
                      int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE);
                     T t = tableview.getItems().remove(draggedIndex);
                     int dropIndex ;
                      if (row.isEmpty()) {
                          dropIndex = tableview.getItems().size() ;
                      } else {
                          dropIndex = row.getIndex();
                      tableview.getItems().add(dropIndex, t);
                      event.setDropCompleted(true);