JavaFx TableView 实现的基于桌面应用的增删改查

2022-06-01  本文已影响0人  程就人生

做Web开发很多年,桌面应用太久没碰了。现在市面上有很多桌面应用,PC版的,手机版的,大多是用其他语言写的。作为一名Java语言的忠实粉丝,还是想用 Java 语言来做一个桌面应用。闲话少说,现在就来做个增删改查吧。

本Demo实现功能:
1.TableView列表checkbox框、序号、文本、下拉框内容的展示;
2.在TableView中对文本、下拉框编辑并保存;
3.新增一列到TableView列表中;
4.勾选一列或多列进行删除操作;
一、开发环境说明;

springboot 2.1.4.RELEASE
jdk 1.8

二、pom引入架包;

<!-- springboot整合javafx start  -->
   <dependency>
      <groupId>de.roskenet</groupId>
      <artifactId>springboot-javafx-support</artifactId>
      <version>2.1.6</version>
    </dependency>
 <!-- springboot整合javafx end  -->
 <!-- lombok start  -->
    <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
    </dependency>
<!-- lombok end  -->

三、实现代码;

1.一个用户bean;


import lombok.Data;
/**
 * 用户Bean
 * @author 程就人生
 * @Date
 */
@Data
public class User {

  public User(String name, String uid, int sex) {
    this.name = name;
    this.uid = uid;
    this.sex = sex;
  }

  private String name;
  
  private String uid;
  
  private int sex;
}

2.一个性别枚举类;


import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
/**
 * 性别枚举
 * @author 程就人生
 * @Date
 */
public enum Sex {

  MALE(1, "男"),
   
  FEMALE(0, "女");

    private int key;
    
    private String value;

    Sex(Integer key, String value) {
        this.key = key.intValue();
        this.value = value;
    }

    public int key() {
        return key;
    }

    public String getValue() {
        return value;
    }
    
    /**
     * 获取所有的value值
     * @return
     */
    public static List<String> valueList(){
      List<String> values = new ArrayList<String>();
        for (Sex testEnum : EnumSet.allOf(Sex.class)) {
          values.add(testEnum.value);
        }
        return values;
    }
    
    /**
     * 通过key获取value
     * @param key
     * @return
     */
    public static String getValue(Integer key) {
      Sex[] sexs = values();
        for (Sex sex : sexs) {
            if (sex.key() == key) {
                return sex.value;
            }
        }
        return null;
    }

    /**
     * 通过value获取key
     * @param value
     * @return
     */
    public static Integer getKey(String value) {
      Sex[] sexs = values();
        for (Sex sex : sexs) {
            if (sex.value.equals(value)) {
                return sex.key();
            }
        }
        return null;
    }
}

3.核心代码;

import java.util.ArrayList;
import java.util.List;

import org.springframework.util.StringUtils;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.ChoiceBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;


/**
 * 参考官网:https://docs.oracle.com/javafx/2/ui_controls/table-view.htm
 * 可编辑tableview示例
 * @author 程就人生
 * @Date
 */
@Slf4j
@SuppressWarnings("restriction")
public class TableViewSamle extends Application {
    
  // tableview列表
  private TableView<User> tableView = new TableView<User>();
    // 用户获取
    private final ObservableList<User> data =
            FXCollections.observableArrayList(
            new User("张三","001",1),
            new User("李四","002",1),
            new User("王五","003",1));
    final HBox hb = new HBox();
    // 被选中的uid
    private List<String> uids = new ArrayList<String>();
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("用户信息");
        stage.setWidth(450);
        stage.setHeight(550);
        
        // 设置为可编辑
        tableView.setEditable(true);
        
        // 复选框
        TableColumn<User,String> checkboxCol = new TableColumn<User,String>("");
        checkboxCol.setMinWidth(50);
        // 展示值设置
        checkboxCol.setCellValueFactory(new PropertyValueFactory<User, String>("uid"));
        // 多选框展示
        checkboxCol.setCellFactory(new Callback<TableColumn<User, String>, TableCell<User, String>>() {
          @Override
          public TableCell<User, String> call(TableColumn<User, String> param) {
              TextFieldTableCell<User, String> cell = new TextFieldTableCell<User, String>(){
                  @Override
                  public void updateItem(String item, boolean empty) {
                    // 不为空时再展示
                    if(!StringUtils.isEmpty(item) && !empty){
                      CheckBox checkBox = new CheckBox();
                      HBox hbox = new HBox();
                          hbox.setAlignment(Pos.CENTER);
                          hbox.getChildren().add(checkBox);
                          // 增加监听
                          checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                  if(newValue){
                    uids.add(item);
                  }else{
                    uids.remove(item);
                  }
                }                          
                          });                        
                          this.setGraphic(hbox);
                    }                    
                  }
              };
              return cell;
          }
      });
        
        // 序号展示
        TableColumn<User,String> indexCol = new TableColumn<User,String>("序号");
        indexCol.setMinWidth(50);
        indexCol.setCellValueFactory(new PropertyValueFactory<User, String>("uid"));
        // 设置序号展示
        indexCol.setCellFactory(new Callback<TableColumn<User, String>, TableCell<User, String>>() {
           @Override
           public TableCell<User, String> call(TableColumn<User, String> param) {
               TableCell<User, String> cell = new TableCell<User, String>(){
                   @Override
                   public void updateItem(String item, boolean empty) {
                     super.updateItem(item, empty);
                       this.setText(null);
                       this.setGraphic(null);
                       if (!empty) {
                           int rowIndex = this.getIndex() + 1;
                           this.setText(String.valueOf(rowIndex));
                       }
                   }
                 };
               return cell;
            }
         });
 
        // 员工号的展示和编辑
        TableColumn<User,String> uidCol = new TableColumn<User,String>("员工号");
        uidCol.setMinWidth(100);
        uidCol.setCellFactory(TextFieldTableCell.forTableColumn());
        uidCol.setCellValueFactory(new PropertyValueFactory<User, String>("uid"));
        // 对编辑进行监听,必须按回车才能监听到更改事件
        uidCol.setOnEditCommit(new EventHandler<CellEditEvent<User, String>>() {
             @Override
             public void handle(CellEditEvent<User, String> t) {
              // 更新改变的值
               User temp = ((User) t.getTableView().getItems().get(t.getTablePosition().getRow()));  
               temp.setUid(t.getNewValue());
               // TODO 其他操作
               log.info("最新输入的值{}", t.getNewValue());
               log.info(temp.toString());
             }
         });
        
        // 姓名的展示和编辑
        TableColumn<User,String> nameCol = new TableColumn<User,String>("姓名");
        nameCol.setMinWidth(100);
        // 设置为可编辑的,如果是其他类型,可使用 new IntegerStringConverter()等转换
        // 参考:https://docs.oracle.com/javase/8/javafx/api/javafx/util/StringConverter.html
        nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
        nameCol.setCellValueFactory(new PropertyValueFactory<User, String>("name"));
        // 对编辑进行监听,必须按回车才能监听到更改事件
        nameCol.setOnEditCommit(new EventHandler<CellEditEvent<User, String>>() {
             @Override
             public void handle(CellEditEvent<User, String> t) {
              // 更新改变的值
               User temp = ((User) t.getTableView().getItems().get(t.getTablePosition().getRow()));  
               temp.setName(t.getNewValue());
               // TODO 其他操作
               log.info("最新输入的值{}", t.getNewValue());
               log.info(temp.toString());
             }
         });
        
 
        TableColumn<User,String> sexCol = new TableColumn<User,String>("性别");
        sexCol.setMinWidth(50);
        sexCol.setCellValueFactory(new PropertyValueFactory<User, String>("sex"));
        // 性别下拉框的展示
        sexCol.setCellValueFactory(new Callback<CellDataFeatures<User, String>, ObservableValue<String>>() {
          public ObservableValue<String> call(CellDataFeatures<User, String> p) {
            // 通过产品名称获取产品型号编码
              return new ReadOnlyObjectWrapper<String>(Sex.getValue(p.getValue().getSex()));
          }
     });
     // 性别的获取
     sexCol.setCellFactory(ChoiceBoxTableCell.forTableColumn(FXCollections.observableArrayList(Sex.valueList())));        
     // 对编辑进行监听,必须按回车才能监听到更改事件
     sexCol.setOnEditCommit(new EventHandler<CellEditEvent<User, String>>() {
             @Override
             public void handle(CellEditEvent<User, String> t) {
               User temp = ((User) t.getTableView().getItems().get(t.getTablePosition().getRow()));
               // 通过value获得key
               temp.setSex(Sex.getKey(t.getNewValue())); 
             }
         }); 
        // 数据填充
        tableView.setItems(data);
        tableView.getColumns().add(checkboxCol);
        tableView.getColumns().add(indexCol);
        tableView.getColumns().add(uidCol);
        tableView.getColumns().add(nameCol);
        tableView.getColumns().add(sexCol);
 
        final TextField addUid = new TextField();
        addUid.setMaxWidth(uidCol.getPrefWidth());
        addUid.setPromptText("员工号");
        
        final TextField addName = new TextField();
        addName.setPromptText("姓名");
        addName.setMaxWidth(nameCol.getPrefWidth());        
        
        // 性别下拉框
        final ChoiceBox<String> addSex = new ChoiceBox<String>();
        addSex.getItems().addAll(Sex.valueList());
        addSex.setMaxWidth(sexCol.getPrefWidth());
        // 默认选第一个
        addSex.getSelectionModel().select(0);
 
        final Button addButton = new Button("增加");
        addButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                data.add(new User(addName.getText(),addUid.getText(),Sex.getKey(addSex.getSelectionModel().getSelectedItem().toString())));
                addUid.clear();
                addName.clear();
                addSex.getSelectionModel().select(0);
                // 表格刷新
                tableView.refresh();
            }
        });
 
        final Button delButton = new Button("删除");
        delButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
              uids.stream().forEach(uid->{
                data.remove(data.stream().filter(user->user.getUid().equals(uid)).findFirst().get());
              });
              // 删除后清空checkbox
              uids.clear();
              // 表格刷新
                tableView.refresh();
            }
        });
        
        final Label label = new Label("用户列表");
        label.setFont(new Font("Arial", 20)); 
        
        hb.getChildren().addAll(addUid, addName, addSex, addButton);
        hb.setSpacing(3);
 
        HBox hb2 = new HBox();
        hb2.setSpacing(5);
        // 设置padding 上、右、低、左
        hb2.setPadding(new Insets(10, 0, 0, 10));
        hb2.getChildren().addAll(label,delButton);
        
        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(hb2, tableView, hb);
 
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
 
        stage.setScene(scene);
        stage.show();
    }
}

4.运行结果;


问题总结:

1. 在tableview对文本进行编辑的时候,为什么监听事件不生效?

文本输入后,需要按下回车键,监听事件才能生效。

2. choicebox 有value和lable,怎么展示?

看demo,展示用label,存储用value,在setCellValueFactory中设置展示,在setOnEditCommit中监听保存。

3.如果字段不是String类型,在setCellFactory时该如何设置?

除了String类型,还支持很多其他类型,比如:IntegerStringConverter等;

table-view 参考文档:

https://docs.oracle.com/javafx/2/ui_controls/table-view.htm

类型转换参考文档:

https://docs.oracle.com/javase/8/javafx/api/javafx/util/StringConverter.html

lombok使用参考:

Lombok中@Data等注解的使用

最后总结

JavaFx还有很多架包可以使用,包括样式上的封装,控件的再次封装、功能增强等等,但是基本用法都是一样的。当然上面的demo简单了点,样式上也丑了点,但这只是个开始,一切都会越来越好的。

上一篇下一篇

猜你喜欢

热点阅读