赞
踩
第一次写文章,质量请海涵!
最近有被要求做一个简单的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); } } }
看起来是完成了我要的需求,但是,故事还没结束。。。。。。
这个check state太出戏了,怎么可能不用checkBox呢?!
其实我一开始是打算直接checkBox的,但是tableview里放插件真的好不舒服,一点没有js那种随便定位到目标元素然后操作的感觉。我们拿check state开刀,加了一句
firstNameCol.setCellFactory(CheckBoxTableCell.forTableColumn(firstNameCol));
这行代码非常直接地给我的表格第一列画上了漂亮的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); } }
对应的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);
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); } } }
当然,点击事件的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; });
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。