当前位置:   article > 正文

javafx tableview中checkbox的全选/反选_cellfactory.tablecheckboxcolumn 全选

cellfactory.tablecheckboxcolumn 全选

第一次写文章,质量请海涵!
最近有被要求做一个简单的javafx桌面应用程序,需要检索目录下的文件,勾选进行文件处理。

这里用到了tableview,可以看到表格的两列check state和File Name都是string类的,点击某列之后check state会改为选定/非选定,同时将选中行的File Name存入list,代码如下:

public class HelloWorld extends Application {
	@FXML
	private final TableView<FileSearch> table = new TableView<>();
	@FXML
	private final ObservableList<FileSearch> data = FXCollections.observableArrayList();
	
	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage primaryStage) {
		GridPane grid = new GridPane();		
		Button btSelect = new Button("全選択");
		btSelect.setId("btSelect");
		grid.add(btSelect, 0, 1);

		final VBox vbox = new VBox();
		vbox.getChildren().addAll(table);
		grid.add(vbox, 0, 2);

		TableColumn firstNameCol = new TableColumn("checkState");
		//checkState以及下面的lastName都是和FileSearch中的属性对应的!
		//这句的完全写法应该是 TableColumn<FileSearch,String> firstNameCol = new TableColumn<FileSearch,String>("checkState"); 这样看起来好多了。
		firstNameCol.setCellValueFactory(new PropertyValueFactory<>("checkState"));
		
		TableColumn<FileSearch,String> lastNameCol = new TableColumn<FileSearch,String>("File Name");
		lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
		table.getColumns().addAll(firstNameCol, lastNameCol);
		
		//表格绑定的点击事件
		//changeList存放选中行的文件名
		List<String> changeList = new ArrayList<>();
		table.setRowFactory(tv -> {
			TableRow<FileSearch> row = new TableRow<>();
			row.setOnMouseClicked(event -> {
				if(!row.isEmpty()) {
					//取到当前选定行的文件名
					String rowData = row.getItem().lastName.getValue();
					//下面的rowData是我对路径格式进行的处理,可忽略
					String[] list = rowData.split("\\\\" );
					rowData = '"' + list[list.length-1].split("\\.")[0] + '"';
					if (row.getItem().getCheckState()== "disSelected") {
						data.get(row.getIndex()).setCheckState("selected");
						//必须刷新一下表,否则值改变了但是表中不动态显示
						table.refresh();
						changeList.add(rowData);
					}else {
					//再次点击从changeList移除选定文件
						row.getItem().setCheckState("disSelected");
						table.refresh();
						remove(changeList, rowData);
					}
				}
			});
			
			//全选/反选按钮点击事件
			btSelect.setOnMouseClicked(event -> {
				if(btSelect.getText() == "全選択") {
					btSelect.setText("全選択解除");
				}else {
					btSelect.setText("全選択");
				}
				table.getItems().forEach(e ->{
					if (e.getCheckState()== "disSelected") {
						e.setCheckState("selected");
						table.refresh();
						changeList.add(e.lastName.getValue());
					}else {
						e.setCheckState("disSelected");
						table.refresh();
						remove(changeList, e.lastName.getValue());
					}
				});
			});
			return row;
		});
		
		primaryStage.setResizable(false);// 窗体缩放(默认为true)
		primaryStage.setScene(scene);
		primaryStage.show();
	}

	public static class FileSearch {
//		private SimpleBooleanProperty box = new SimpleBooleanProperty();
		private SimpleStringProperty checkState = new SimpleStringProperty();
		private SimpleStringProperty lastName = new SimpleStringProperty();
		
		private FileSearch(Boolean cBox, String lName) {
			this.checkState = new SimpleStringProperty(fName);
//			this.box = new SimpleBooleanProperty(cBox);
			this.lastName = new SimpleStringProperty(lName);
		}

		public String getCheckState() {
			return checkState.get();
		}

		public void setCheckState(String fName) {
			checkState.set(fName);
		}
		
//		public Boolean getBox() {
//			return box.get();
//		}

//		public void setBox(Boolean cBox) {
//			box.set(cBox);
//		}

		public String getLastName() {
			return lastName.get();
		}

		public void setLastName(String lName) {
			lastName.set(lName);
		}
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

看起来是完成了我要的需求,但是,故事还没结束。。。。。。
这个check state太出戏了,怎么可能不用checkBox呢?!
其实我一开始是打算直接checkBox的,但是tableview里放插件真的好不舒服,一点没有js那种随便定位到目标元素然后操作的感觉。我们拿check state开刀,加了一句

	firstNameCol.setCellFactory(CheckBoxTableCell.forTableColumn(firstNameCol));
  • 1

这行代码非常直接地给我的表格第一列画上了漂亮的checkBox(还是自动居中的):
在这里插入图片描述
然后我凉了,花了一天也搞不定这个checkBox的定位,按道理来说应该是非常简单的,毕竟table的点击事件确定第几行后直接给checkBox设定true和false即可,但是现在我怎么点也没反应。搞不定,注掉它!

可能你已经注意到了FileSearch中注释部分,那正是我接下来要干的事情。
我们干掉checkState,加一个Boolean类的Box。

public static class FileSearch {

		private SimpleBooleanProperty box = new SimpleBooleanProperty();
//		private SimpleStringProperty checkState = new SimpleStringProperty();
		private SimpleStringProperty lastName = new SimpleStringProperty();
		
		private FileSearch(Boolean cBox, String lName) {
//			this.checkState = new SimpleStringProperty(fName);
			this.box = new SimpleBooleanProperty(cBox);
			this.lastName = new SimpleStringProperty(lName);
		}

//		public String getCheckState() {
//			return checkState.get();
//		}
//
//		public void setCheckState(String fName) {
//			checkState.set(fName);
//		}
		
		public Boolean getBox() {
			return box.get();
		}

		public void setBox(Boolean cBox) {
			box.set(cBox);
		}

		public String getLastName() {
			return lastName.get();
		}

		public void setLastName(String lName) {
			lastName.set(lName);
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

对应的firstNameCol也换成box

Callback<TableColumn<FileSearch, Boolean>, TableCell<FileSearch, Boolean>> booleanCellFactory = 
	            new Callback<TableColumn<FileSearch, Boolean>, TableCell<FileSearch, Boolean>>() {
	            @Override
	                public TableCell<FileSearch, Boolean> call(TableColumn<FileSearch, Boolean> p) {
	                    return new BooleanCell();
	            }
	        };
	        firstNameCol.setCellValueFactory(new PropertyValueFactory<FileSearch,Boolean>("box"));
	        firstNameCol.setCellFactory(booleanCellFactory);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
class BooleanCell extends TableCell<FileSearch, Boolean> {
        private CheckBox checkBox;
        public BooleanCell() {
            checkBox = new CheckBox();
            checkBox.setDisable(true);
            checkBox.selectedProperty().addListener(new ChangeListener<Boolean> () {
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    if(isEditing())
                        commitEdit(newValue == null ? false : newValue);
                }
            });
            this.setGraphic(checkBox);
            this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            this.setEditable(true);
        }
        @Override
        public void startEdit() {
            super.startEdit();
            if (isEmpty()) {
                return;
            }
            checkBox.setDisable(false);
            checkBox.requestFocus();
        }
        @Override
        public void cancelEdit() {
            super.cancelEdit();
            checkBox.setDisable(true);
        }
        public void commitEdit(Boolean value) {
            super.commitEdit(value);
            checkBox.setDisable(true);
        }
        @Override
        public void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
            if (!isEmpty()) {
                checkBox.setSelected(item);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

当然,点击事件的get set方法记得一起改了:

table.setRowFactory(tv -> {
			TableRow<FileSearch> row = new TableRow<>();
			row.setOnMouseClicked(event -> {
				if(!row.isEmpty()) {
					String rowData = row.getItem().lastName.getValue();
					String[] list = rowData.split("\\\\" );
					rowData = '"' + list[list.length-1].split("\\.")[0] + '"';
					if (row.getItem().getBox()== false) {
						data.get(row.getIndex()).setBox(true);
						table.refresh();
						changeList.add(rowData);
					}else {
						row.getItem().setBox(false);
						table.refresh();
						remove(changeList, rowData);
					}
				}
			});
			btSelect.setOnMouseClicked(event -> {
				if(btSelect.getText() == "全選択") {
					btSelect.setText("全選択解除");
				}else {
					btSelect.setText("全選択");
				}
				table.getItems().forEach(e ->{
					if (e.getBox()== false) {
						e.setBox(true);
						table.refresh();
						changeList.add(e.lastName.getValue());
					}else {
						e.setBox(false);
						table.refresh();
						remove(changeList, e.lastName.getValue());
					}
				});
			});
			return row;
		});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/191676
推荐阅读
相关标签
  

闽ICP备14008679号