当用户单击复选框时,我不会在CheckBoxTableCell
中使用TableView
。
需要在选中CheckBox之前以及更改关联属性之前执行此代码。
由于CheckBoxTableCell
不会触发startEdit()
,commitEdit()
等,因此我还需要放置代码。updateItem()
为时已晚,因为此处的值已更改。
有人知道我可以在其他地方插入我的代码吗?还是我最好只编写自己的CheckBoxTableCell?
对于那些想进一步思考的人:当用户选中复选框时,我想运行一个代码,该代码检查他的决定是否会在以后导致他的问题。当属性更改时,我有一个changeListener,它将新值上传到数据库。如果可能有任何问题(我的代码返回true),则应该出现强制性错误消息:“您真的要执行此操作吗……blabla”,并且只有当他确认应该实际选中复选框时,该值才会更改并上传到数据库。
这就是我设置CheckBoxTableCell
的方法:
//init cell factories
Callback<TableColumn<PublicMovie, Boolean>, TableCell<PublicMovie, Boolean>> checkBoxCellFactory
= (TableColumn<PublicMovie, Boolean> p) -> new CheckBoxTableCell<>();
//Assign Column
allMoviesCheckBoxColumn = (TableColumn<PublicMovie, Boolean>) allMoviesTableView.getColumns().get(0);
//Set CellValueFactory
allMoviesCheckBoxColumn.setCellValueFactory(cellData -> cellData.getValue().getSomeBooleanProperty();
someBooleanProperty
有一个侦听器。更改为true时,statusProperty
更改为1
。此代码段位于
TableView
的基础类的构造函数中。每当用户单击CheckBox时,都会执行该复选框。 this.status.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
DataHandler.fireOnChangedEvent(PublicMovieChangeListener.STATUS_CHANGED, getMovie(), newValue, oldValue);
});
DataHandler
包含Listeners
的列表(到目前为止只有一个)。当onChange
调用DataHandler
事件时,将执行以下代码:@Override
public void onChange(int changeID, PublicMovie changedPublicMovie, Object newValue, Object oldValue) {
switch (changeID) {
case STATUS_CHANGED:
boolean mayUpdate = check();
//check is a placeholder for the code that checks for problems.
//It will return false if there might be a problem.
if(!mayUpdate){
mayUpdate = ErrorDialogs.getConfirmationDialog("Überfüllung!", header, content);
}
if (mayUpdate) {
updateMovie(changedPublicMovie);
} else {
changedPublicMovie.getStatusProperty().set((int) oldValue);
refreshAllMoviesTable();
}
break;
case THREE_DIM_CHANGED:
updateMovie(changedPublicMovie);
break;
case CHILDREN_CHANGED:
updateMovie(changedPublicMovie);
break;
}
您在这里看到的是我试图撤消更改后的属性...,但该复选框仍处于选中状态。因此,我正在寻找一种在更改属性之前执行检查的方法。
最佳答案
根据 CheckBoxTableCell
的文档:
如果您想收到更改通知,建议直接
观察由CheckBox
操作的布尔属性。
我并不是说CheckBoxTableCell
是不可能的,但很可能不是那么简单。
在大多数情况下,可以使用EventFilter
来管理这种“预选”事件。
因此,您可以尝试将普通的TableColumn
与使用这些cellFactory
的适当EventFilter
一起使用。
我的示例
使用的cellFactory
:
tableCol.setCellFactory(p -> {
CheckBox checkBox = new CheckBox();
TableCell<Person, Boolean> tableCell = new TableCell<Person, Boolean>() {
@Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null)
setGraphic(null);
else {
setGraphic(checkBox);
checkBox.setSelected(item);
}
}
};
checkBox.addEventFilter(MouseEvent.MOUSE_PRESSED, event ->
validate(checkBox, (Person) cell.getTableRow().getItem(), event));
checkBox.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(event.getCode() == KeyCode.SPACE)
validate(checkBox, (Person) cell.getTableRow().getItem(), event);
});
tableCell.setAlignment(Pos.CENTER);
tableCell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
return tableCell;
});
和使用的
validate
方法:private void validate(CheckBox checkBox, Person item, Event event){
// Validate here
event.consume();
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");
// Set the checkbox if the user want to continue
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK)
checkBox.setSelected(!checkBox.isSelected());
}
是做什么的:
它呈现一个简单的
CheckBox
,并向此EventFilter
添加两个CheckBox
。第一个在鼠标按下时执行,第二个在按键上执行(此处使用KeyCode.SPACE
)。他们两个都调用validate
方法。 validate
方法使用事件(确保未修改CheckBox
的选择状态),“验证”输入(我这边没有验证),然后显示确认对话框。如果用户同意,则设置selectedProperty
的CheckBox
。