JavaFX CheckBoxTableCell捕获ClickEvent

时间:2016-09-01 11:13:33

标签: java javafx tableview

使用CheckBoxTableCell中的TableView我不想在用户点击复选框时执行某些代码。 需要在检查CheckBox之前以及关联属性更改之前执行此代码。

由于CheckBoxTableCell没有触发startEdit()commitEdit()等等,我需要另外一点来处理我的代码。

updateItem()为时已晚,因为价值已经在那里改变了。

有人知道我可以插入代码的任何其他地方吗?或者我最好只编写自己的CheckBoxTableCell?

对于那些想要进一步思考的人:当用户检查checkBox时,我想运行一个代码,检查他的决定是否可能导致他以后出现问题。当属性更改时,我有一个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;
    }

您在此处看到的是我尝试撤消已更改的属性...但复选框仍保持选中状态。因此,我正在寻找一种在更改属性之前执行检查的方法。

1 个答案:

答案 0 :(得分:2)

基于CheckBoxTableCell的文档:

  

如果您希望收到更改通知,建议直接进行   观察由CheckBox操纵的布尔属性。

我不能说CheckBoxTableCell是不可能的,但很可能不是那么简单。

这种&#34;预选&#34;在EventFilter s。

的大多数情况下,可以管理事件

因此,您可以尝试将普通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的选择状态未被修改),&#34;验证&#34;输入(我没有验证)然后显示确认对话框。如果用户同意,则设置selectedProperty的{​​{1}}。