javafx tableview中checkbox的全选/反选
程序员文章站
2024-02-05 12:00:40
...
第一次写文章,质量请海涵!
最近有被要求做一个简单的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;
});
上一篇: 购物车的拖放事件
下一篇: JavaFX控件——TableView
推荐阅读
-
javafx tableview中checkbox的全选/反选
-
Android checkbox的listView(多选,全选,反选)具体实现方法
-
Android checkbox的listView(多选,全选,反选)具体实现方法
-
android 实现ListView嵌套Checkbox实现真正的多选、全选、反选、取消
-
利用Vue.js实现checkbox的全选反选效果
-
jquery 操作checkbox的例子(全选,反选,获取选取值)
-
vue2.0在table中实现全选和反选的示例代码
-
jquery中checkbox的全选与反选
-
关于Winform下DataGridView中实现checkbox全选反选、同步列表项的处理
-
bootstrap中checkbox全选,反选