美文网首页
JavaFx TableView 实现的基于桌面应用的增删改查

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

作者: 程就人生 | 来源:发表于2022-06-01 21:59 被阅读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简单了点,样式上也丑了点,但这只是个开始,一切都会越来越好的。

    相关文章

      网友评论

          本文标题:JavaFx TableView 实现的基于桌面应用的增删改查

          本文链接:https://www.haomeiwen.com/subject/lhlfmrtx.html