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

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

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

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

代码实现:

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 tableView = new TableView();
    // 用户获取
    private final ObservableList 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 uids = new ArrayList();
    // 上移按钮
    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 checkboxCol = new TableColumn("");
        checkboxCol.setMinWidth(50);
        // 展示值设置
        checkboxCol.setCellValueFactory(new PropertyValueFactory("uid"));
        // 多选框展示
        checkboxCol.setCellFactory(new Callback, TableCell>() {
          @Override
          public TableCell call(TableColumn param) {
              TextFieldTableCell cell = new TextFieldTableCell(){
                  @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() {
                @Override
                public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) {
                  if(newValue){
                    uids.add(item);
                  }else{
                    uids.remove(item);
                  }
                }                          
                          });                        
                          this.setGraphic(hbox);
                    }                    
                  }
              };
              return cell;
          }
      });       


     // 员工号的展示和编辑
        TableColumn uidCol = new TableColumn("员工号");
        uidCol.setMinWidth(100);
        uidCol.setCellFactory(TextFieldTableCell.forTableColumn());
        uidCol.setCellValueFactory(new PropertyValueFactory("uid"));

        // 姓名的展示和编辑
        TableColumn nameCol = new TableColumn("姓名");
        nameCol.setMinWidth(100);
        nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
        nameCol.setCellValueFactory(new PropertyValueFactory("name")); 

        TableColumn sexCol = new TableColumn("性别");
        sexCol.setMinWidth(50);
        sexCol.setCellValueFactory(new PropertyValueFactory("sex"));
        // 性别下拉框的展示
        sexCol.setCellValueFactory(new Callback, ObservableValue>() {
          public ObservableValue call(CellDataFeatures p) {
            // 通过产品名称获取产品型号编码
              return new ReadOnlyObjectWrapper(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() {
            @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() {
            @Override
            public void handle(ActionEvent e) {
              upMove();
            }
        });

        downButton = new Button("下移");
        downButton.setVisible(false);
        downButton.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent e) {
              downMove();
            }
        });

        saveButton = new Button("保存排序");
        saveButton.setVisible(false);
        saveButton.setOnAction(new EventHandler() {
            @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 -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 勾选多条数据上下移动排序)