JavaFX TableView与Custom Cell Datepicker" OnEditCommit"没有被调用

时间:2014-03-25 14:18:27

标签: datepicker javafx tableview cell java-8

大家好!

我正在使用JavaFX和JDK 8.

我使用JavaFX POJO类“输入”得到了一个由数据库填充的 TableView。我已经成功实现了TexField单元格,ComboBoxes单元格和Checkbox单元格。

但是我无法使用DatePicker Control:“setOnEditComit”上的事件永远不会被调用...

Hre是我的代码:

TableColumn的声明:

    @FXML
    private TableColumn<Inputs,LocalDate> colDate = new TableColumn<Inputs,LocalDate>();
     [...]
    colDate.setCellValueFactory(
                        new PropertyValueFactory<Inputs,LocalDate>("localdate"));

        Callback<TableColumn<Inputs, LocalDate>, TableCell<Inputs, LocalDate>> dateCellFactory =
                    new Callback<TableColumn<Inputs, LocalDate>, TableCell<Inputs, LocalDate>>() {
                public TableCell call(TableColumn p) {
                    return new EditingDatePickerCell();
                }
            };

      [...]
    colDate.setOnEditCommit(
                    new EventHandler<CellEditEvent<Inputs, LocalDate>>() {
                        @Override
                        public void handle(CellEditEvent<Inputs, LocalDate> event) {

        System.out.println("EVENT!!!!");
                            ((Inputs) event.getTableView().getItems().get(
                                    event.getTablePosition().getRow())
                                    ).setDatePicker(event.getNewValue());
   }
   }
   );

使用这些JavaFX POJO对象声明:

    public ObjectProperty<LocalDate> localdate; 
     [...]

     this.localdate =  new SimpleObjectProperty<LocalDate>(localdate); 
     [...]
    public LocalDate  getDatePicker() {
            return localdate.getValue();
        }
     [...]
    public void setDatePicker(LocalDate  value) {
            System.out.println("EVENT!!!!");
            localdate.setValue(value);
        }
     [...]
    public ObjectProperty<LocalDate> localdateProperty() {
            return localdate;
        }

EditingDatePickerCell类:

 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;

 import javafx.application.Platform;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.Pos;
 import javafx.scene.control.ContentDisplay;
 import javafx.scene.control.DatePicker;
 import javafx.scene.control.TableCell;
 import javafx.scene.control.TableColumn;
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyEvent;

 import com.desktop.newapp.utils.Inputs;

    public class EditingDatePickerCell <Inputs, LocalDate> extends TableCell<Inputs, LocalDate> {

        @Override
        public void startEdit() {
            if (!isEmpty()) {
                super.startEdit();
                createDatePicker();
                setText(null);
                setGraphic(datePicker);
                datePicker.requestFocus();
            }
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();
            datePicker.setValue((java.time.LocalDate) getItem());
            setGraphic(null);
            setContentDisplay(ContentDisplay.TEXT_ONLY);
        }

        private DatePicker datePicker;

        public EditingDatePickerCell() {
            if (datePicker == null) {
                createDatePicker();
            }
            setGraphic(datePicker);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    datePicker.requestFocus();
                }
            });
        }

        @Override
        public void updateItem(LocalDate item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {

            if (datePicker != null && item != null) {
                datePicker.setValue((java.time.LocalDate) getLocalDate());
                commitEdit(getLocalDate());
            }
                setGraphic(datePicker);
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

            }
        }


        private void createDatePicker() {
            datePicker = new DatePicker();
            datePicker.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
            setGraphic(datePicker);  



            datePicker.addEventFilter(KeyEvent.KEY_PRESSED,new EventHandler<KeyEvent>() { 
                @Override
                public void handle(KeyEvent t) {

                        if (t.getCode() == KeyCode.ENTER) {
                            commitEdit(getLocalDate());
                        } else if (t.getCode() == KeyCode.ESCAPE) {
                            cancelEdit();
                        } else if (t.getCode() == KeyCode.TAB) {
                            commitEdit(getLocalDate());;

                        }
                    }

            });

            setAlignment(Pos.CENTER);
        }

        private LocalDate getLocalDate() {
       return  getItem();
         ///return datePicker.getValue() != null ? datePicker.getValue() : getItem();
        }  
    }

我一直在谷歌搜索,我没有在JavaFX TableView中找到任何正确的Java8 DatePicker编辑功能的实现。任何帮助都会非常感谢 !!

如果没有Stackoverflow,我将无法完成整个工作的四分之一,所以长寿命到Stackoverflow !!

问候。

5 个答案:

答案 0 :(得分:2)

当用户与选择器交互时,您需要将表置于编辑模式(对于当前行)。这可以通过像这样的onShowingHandler来实现(例子也是一个颜色选择器):

this.colorPicker.setOnShowing(event -> {
    final TableView<T> tableView = getTableView();
    tableView.getSelectionModel().select(getTableRow().getIndex());
    tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);       
});

然后像这样观察选择器的valueProperty:

this.colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
    if(isEditing()) {
        commitEdit(newValue);
    }
}); 

有关详细说明,请查看我的博文:Custom editor components in JavaFX TableCells

全班:

public class ColorTableCell<T> extends TableCell<T, Color> {    
    private final ColorPicker colorPicker;

    public ColorTableCell(TableColumn<T, Color> column) {
    this.colorPicker = new ColorPicker();
    this.colorPicker.editableProperty().bind(column.editableProperty());
    this.colorPicker.disableProperty().bind(column.editableProperty().not());
    this.colorPicker.setOnShowing(event -> {
        final TableView<T> tableView = getTableView();
        tableView.getSelectionModel().select(getTableRow().getIndex());
        tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);       
    });
    this.colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
        if(isEditing()) {
        commitEdit(newValue);
        }
    });     
    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }

    @Override
    protected void updateItem(Color item, boolean empty) {
    super.updateItem(item, empty);  

    setText(null);  
    if(empty) {     
        setGraphic(null);
    } else {        
        this.colorPicker.setValue(item);
        this.setGraphic(this.colorPicker);
    } 
    }
}

答案 1 :(得分:0)

你的Model对象有点奇怪。 setDatePickergetDatePicker方法应该被称为setLocaldategetLocaldate,以便与localdateProperty()方法一致,并且(可能重要的是)传递给{的参数{1}}。

我认为这不会导致您观察到的问题,但我看不出还有什么问题。

This example适合我。 看看你是否能看到我所做的不同......

答案 2 :(得分:0)

here is a datapicker cell edit when pressing tab key and go to the next cell 

datePicker.setOnKeyPressed /EventHandler doesnot work with tab
datePicker.EventFilter get called twice

to work arround this you need to add a listner to tableview cell and get date text as string and cast it to localdate

addEventFilter到TableCell演绎对象是一个示例

=&GT; addEventFilter(KeyEvent.KEY_PRESSED,new EventHandler(){...}

    public class DatePickerCell extends TableCell<Deduction, LocalDate> {

    private DatePicker datePicker;
   private TableColumn column;
   // private TableCell cell;

    public DatePickerCell(TableColumn column) { //
        super();

        this.column = column;
        this.datePicker = new DatePicker(getDate());

    }

    @Override
    public void startEdit() {
            if (!isEmpty()) {
                    super.startEdit();
                    createDatePicker();
                    setText(null);
                    setGraphic(datePicker);

                    Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                    datePicker.requestFocus();
                            }
                    });
                    //Platform.runLater(datePicker::requestFocus);
            }
    }

    @Override
    public void updateItem(LocalDate item, boolean empty) {

        super.updateItem(item, empty);

      //  SimpleDateFormat smp = new SimpleDateFormat("dd/MM/yyyy");

       /* if (null == this.datePicker) {
            System.out.println("datePicker is NULL");
        }*/ //TO be reviewed

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {

            if (isEditing()) {
                 if (datePicker != null) {
                        datePicker.setValue(getItem());
                    }
                    setText(null);
                    setGraphic(datePicker);

            } else {
                setText(getItem().toString());
                setGraphic(null);

            }
        }
    }


    private LocalDate getDate() {
            return getItem() == null ? LocalDate.now() : getItem();
        }

    private void createDatePicker() {
        this.datePicker = new DatePicker(getDate());
        datePicker.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);

        this.datePicker.editableProperty().bind(column.editableProperty());
        this.datePicker.disableProperty().bind(column.editableProperty().not());

        this.datePicker.setOnShowing(event -> {

            final TableView tableView = getTableView();
            tableView.getSelectionModel().select(getTableRow().getIndex());
            tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);       


        });

         datePicker.setOnAction((e) -> {
             commitEdit(datePicker.getValue());

                TableColumn nextColumn = getNextColumn(true);

            if (nextColumn != null) {
                    getTableView().edit(getTableRow().getIndex(),
                                    nextColumn);
            }

            });


        datePicker.focusedProperty().addListener(
            new ChangeListener<Boolean>() {
                    @Override
                    public void changed(
                                    ObservableValue<? extends Boolean> arg0,
                                    Boolean arg1, Boolean arg2) {
                            if (!arg2) {


                                    commitEdit(datePicker.getValue());

                            }
                    }
            });



        datePicker.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
              //   System.out.println("setOnKeyPressed datapicker get value  ...." + t.getCode());
                   /* if (t.getCode() == KeyCode.ENTER) {
                            commitEdit(datePicker.getValue());
                            System.out.println("Enter datapicker get value " + datePicker.getValue());
                    } else */if (t.getCode() == KeyCode.ESCAPE) {
                            cancelEdit();
                    } else if (t.getCode() == KeyCode.ENTER){
                            commitEdit(datePicker.getValue());
                       //     System.out.println("Tab datapicker get value " + datePicker.getValue());
                            TableColumn nextColumn = getNextColumn(!t.isShiftDown());
                         //   System.out.println("nextColumn datapicker get value " + nextColumn.getId());
                    if (nextColumn != null) {
                            getTableView().edit(getTableRow().getIndex(),
                                            nextColumn);
                    }

                    }
            }

        });


        addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent event) {
                if (event.getCode() == KeyCode.TAB) {

                    commitEdit(LocalDate.parse(datePicker.getEditor().getText(), DateTimeFormatter.ofPattern("dd/MM/yyyy")));
                     TableColumn nextColumn = getNextColumn(true);
                    if (nextColumn != null) {
                            getTableView().edit(getTableRow().getIndex(),
                                            nextColumn);
                    }
                }

            }

        });




//     
//    //    setAlignment(Pos.CENTER);
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();

            setText(getItem().toString());
            setGraphic(null);
    }



    public DatePicker getDatePicker() {
        return datePicker;
    }


    public void setDatePicker(DatePicker datePicker) {
        this.datePicker = datePicker;
    }

                private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }

        private TableColumn<Deduction, ?> getNextColumn(boolean forward) {
            List<TableColumn<Deduction, ?>> columns = new ArrayList<>();
            for (TableColumn<Deduction, ?> column : getTableView().getColumns()) {
                columns.addAll(getLeaves(column));
            }
            // There is no other column that supports editing.
            if (columns.size() < 2) {
                return null;
            }
            int currentIndex = columns.indexOf(getTableColumn());
            int nextIndex = currentIndex;
            if (forward) {
                nextIndex++;
                if (nextIndex > columns.size() - 1) {
                    nextIndex = 0;
                }
            } else {
                nextIndex--;
                if (nextIndex < 0) {
                    nextIndex = columns.size() - 1;
                }
            }
            return columns.get(nextIndex);
        }

        private List<TableColumn<Deduction, ?>> getLeaves(
                TableColumn<Deduction, ?> root) {
            List<TableColumn<Deduction, ?>> columns = new ArrayList<>();
            if (root.getColumns().isEmpty()) {
                // We only want the leaves that are editable.
                if (root.isEditable()) {
                    columns.add(root);
                }
                return columns;
            } else {
                for (TableColumn<Deduction, ?> column : root.getColumns()) {
                    columns.addAll(getLeaves(column));
                }
                return columns;
            }
        }

}

在您的班级中使用tableview

  Callback cellFactoryDate
                = new Callback<TableColumn, TableCell>() {
                    public TableCell call(TableColumn p) {
                        return new DatePickerCell(p);//DatePickerTest(p)  //DatePickerTest2     //EditingCellDate
                    }
                };


 dateColumn.setCellValueFactory(new PropertyValueFactory<>("date"));
        //   dateColumn.setCellFactory(cellFactoryTest);//cellFactoryDate
        dateColumn.setCellFactory(cellFactoryDate);
        dateColumn.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<Deduction, LocalDate>>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent<Deduction, LocalDate> t) {
                        ((Deduction) t.getTableView().getItems().get(
                                t.getTablePosition().getRow())).setDate(t.getNewValue());
                    }
                }
        );

答案 3 :(得分:0)

我遇到了同样的问题,但我最后用这篇文章解决了这个问题。 JavaFX8 – Render a DatePicker Cell in a TableView。  结果如下图所示。

enter image description here

答案 4 :(得分:-1)

以下是所有自定义控件都可接受的解决方案;此示例使用ColorPicker控件:

所以我最终处理它:在控件的事件中,我通过“((输入)getTableView()。getItems()。get(getTableRow()。getIndex返回使用的POJO对象()“我更新类似于在OnEditCommit方法中完成...

所以对我而言,它看起来像这样(更新颜色):

 ((Inputs) getTableView().getItems().get(
                    getTableRow().getIndex())
                    ).setColor(cp.getValue());

以下是ColorPickerCell的示例 :

public class ColorPickerTableCell<Inputs> extends TableCell<Inputs, Color>{
private ColorPicker cp;

public ColorPickerTableCell(){        
    cp = new ColorPicker(); 
    cp.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            commitEdit(cp.getValue());
            updateItem(cp.getValue(), isEmpty());
            ((Inputs) getTableView().getItems().get(
                    getTableRow().getIndex())
                    ).setColor(cp.getValue());
        }            
    });                
    setGraphic(cp);
    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    setEditable(true);        
}     
@Override
protected void updateItem(Color item, boolean empty) {
    super.updateItem(item, empty);
    cp.setVisible(!empty);
    this.setItem(item);
    cp.setValue(item);
}
}

使用这个简单的JavaFX的POJO:

    public ObjectProperty<Color> color = new SimpleObjectProperty<Color>();

    this.color = new SimpleObjectProperty(color);

    public ObjectProperty<Color> colorProperty() {
    return color;
 }

public void setColor(Color color2) {
    color.set(color2);
}

我不知道这是否是一个很好的方法来实现,但它对我有用...请注意,JavaFX的POJO只能在“ActionEvent”请求(组合框,日期选择器,颜色选择器等)中访问。

此致