美文网首页
JavaFx TableView 勾选多条数据上下移动排序

JavaFx TableView 勾选多条数据上下移动排序

作者: 程就人生 | 来源:发表于2022-06-02 21:31 被阅读0次

    如下图所示,你有对列表中的数据选中后进行上下移动排序吗?

    选中一条数据和选中多条数据的排序算法一样吗?怎么实现的呢?

    最近有这么一个需求,写了一个排序算法。在写的过程中发现,选中一条数据,上下移动是非常简单的。选中多条数据,再进行上下移动就没有那么容易了,需要动脑想一想。现在就把这段算法的实现分享一下。排序算法在该类中的最后一个方法中。

    代码实现:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import org.springframework.util.StringUtils;
    
    import com.example.demo.tableview.Sex;
    import com.example.demo.tableview.User;
    
    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.Label;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableColumn.CellDataFeatures;
    import javafx.scene.control.TableView;
    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;
    
    
    /**
     * 参考官网:https://docs.oracle.com/javafx/2/ui_controls/table-view.htm
     * 可编辑tableview示例
     * @author 程就人生
     * @Date
     */
    @SuppressWarnings("restriction")
    public class TableViewOrderSamle 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),
            new User("alice","004",1),
            new User("andy","005",1),
            new User("feng","006",1),
            new User("zhang","007",1),
            new User("1111","008",1),
            new User("33333","009",1));
            final HBox hb = new HBox();
        // 被选中的uid
        private List<String> uids = new ArrayList<String>();
        // 上移按钮
        private Button upButton;
        // 下移按钮
        private Button downButton;
        // 下移按钮
        private Button saveButton;
    
        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();
                          if(uids.contains(item)){
                            checkBox.setSelected(true);
                          }
                          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> uidCol = new TableColumn<User,String>("员工号");
            uidCol.setMinWidth(100);
            uidCol.setCellFactory(TextFieldTableCell.forTableColumn());
            uidCol.setCellValueFactory(new PropertyValueFactory<User, String>("uid"));
    
            // 姓名的展示和编辑
            TableColumn<User,String> nameCol = new TableColumn<User,String>("姓名");
            nameCol.setMinWidth(100);
            nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
            nameCol.setCellValueFactory(new PropertyValueFactory<User, String>("name")); 
    
            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())));        
    
            // 数据填充
            tableView.setItems(data);
            tableView.getColumns().add(checkboxCol);
            tableView.getColumns().add(uidCol);
            tableView.getColumns().add(nameCol);
            tableView.getColumns().add(sexCol);
    
    
    
            final Button orderButton = new Button("排序");
            orderButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                  upButton.setVisible(true);
                  downButton.setVisible(true);
                  saveButton.setVisible(true);
                  orderButton.setVisible(false);
                }
            });
    
            upButton = new Button("上移");
            upButton.setVisible(false);
            upButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                  upMove();
                }
            });
    
            downButton = new Button("下移");
            downButton.setVisible(false);
            downButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                  downMove();
                }
            });
    
            saveButton = new Button("保存排序");
            saveButton.setVisible(false);
            saveButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent e) {
                  upButton.setVisible(false);
                  downButton.setVisible(false);
                  saveButton.setVisible(false);
                  orderButton.setVisible(true);
                  // 保存排序
                  saveOrder();
    
                }
            });
    
            final Label label = new Label("用户列表");
            label.setFont(new Font("Arial", 20)); 
    
            HBox hb2 = new HBox();
            hb2.setSpacing(5);
            // 设置padding 上、右、低、左
            hb2.setPadding(new Insets(10, 0, 0, 10));
            hb2.getChildren().addAll(label,orderButton,upButton, downButton, saveButton);
    
            final VBox vbox = new VBox();
            vbox.setSpacing(5);
            vbox.setPadding(new Insets(10, 0, 0, 10));
            vbox.getChildren().addAll(hb2, tableView);
    
            ((Group) scene.getRoot()).getChildren().addAll(vbox);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * 上移操作
         */
        private void upMove(){
          order(-1);
        }
    
        /**
         * 下移操作
         */
        private void downMove(){
          order(1);
        }
    
        /**
         * 保存排序
         */
        private void saveOrder(){
          // 清空所选
          uids.clear();
          // 表格刷新
          tableView.refresh();
        }
    
        /**
         * 排序
         * @param flag
         */
        private void order(int flag){
          // 数据总量
        int size = data.size();
        // 需要移动的数据
        User findSensor;
        // 被移动的数据
        User tempSensor;
        // 定义一个数组,获取被选中数据的实际顺序    
        String[] orderUsers = new String[size];
        // 默认填充null
        Arrays.fill(orderUsers, null);
        for(String uid : uids){
          findSensor = data.stream().filter(sensor->sensor.getUid().equals(uid)).findFirst().get();
          orderUsers[data.indexOf(findSensor)] = uid;
        }
        // 向上移动
        if(flag == -1){        
          for(int i=0;i<size;i++){
            if(!StringUtils.isEmpty(orderUsers[i])){
              if(i + flag > -1){
                tempSensor = data.get(i + flag);
                findSensor = data.get(i);
                // 互换位置
                data.set(i, tempSensor);
                data.set(i + flag, findSensor);
              }
            }
          }
        }else{      
          // 向下移动
          for(int i = size -1; i > -1 ; i--){
            if(!StringUtils.isEmpty(orderUsers[i])){
              if(i < size-1 && i + flag < size){
                tempSensor = data.get(i + flag);
                findSensor = data.get(i);
                data.set(i, tempSensor);
                data.set(i + flag, findSensor);
              }
            }
          }
        }
        // 排序后,列表展示刷新
        tableView.refresh();
        }
    }
    

    说明:该类中的最后一个方法,是上下移动排序的算法。我们对于要选择的数据,是没有规则的,有可能先勾选这条数据,然后再勾选那条数据,既有可能点击向上移动,又有可能点击向下移动。

    因此,在本算法中,先查找每条选中数据在所有数据中的索引。然后再看是上移,还是下移。如果是上移,把每条数据和所在索引的上一条数据互换位置即可。如果是下移,那么就需要反向变换位置,先移动索引在下面的数据,再移动索引在上面的数据,把数据所在索引和下一条索引的数据互换位置即可。

    写在最后

    除此之外,我们还可能遇到依据某个字段排序,升序排,降序排。对List集合排序,如果想要按照某个字段升序、降序排序,在现有数据上排序,可以直接使用JDK中的工具类,而不必再去查询一次数据库。

    // 对list排序
    Collections.sort(data, Comparator.comparing(User::getUid).reversed());
    Collections.sort(data, Comparator.comparing(User::getUid));
    

    JavaFx 相关资料参考:

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

    如何使用2020版IDEA开发JavaFx8,IDEA的配置及一些小技巧

    SpringBoot整合JavaFx、Jfoenix开发第一个简单的应用,登录及页面跳转

    安装IDEA 2018.3.6,打开个JavaFx桌面小应用,踩到的一些坑

    相关文章

      网友评论

          本文标题:JavaFx TableView 勾选多条数据上下移动排序

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