从TableView单元格中删除Datepicker渲染(JavaFX8)

时间:2017-10-19 14:07:01

标签: java datepicker tableview javafx-8

我有一个包含2列“Date”(LocalDate)和“FX”(Double)的TableView。我已启用单元格编辑并按照我在此处找到的示例(http://physalix.com/javafx8-render-a-datepicker-cell-in-a-tableview/)创建了一个自定义CellFactory,它为“Date”列的单元格显示DatePicker。此解决方案虽然立即呈现DatePciker,所以我更改了我的代码以仅在用户双击任何(非空)Date单元格时显示DatePicker。到目前为止一切都很好......

如何在用户更改日期或取消输入后“返回”并从单元格中删除DatePicker渲染?参见图片作为参考。图1是列表的初始状态。双击后是图2。如何返回Pic 1状态?如果您需要查看我的具体代码,请告诉我。

Reference pictures

这是检查双击然后创建CellFactory

的代码
 fxTable.getSelectionModel().setCellSelectionEnabled(true);
    fxTable.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            if (event.getClickCount() == 2) {
                TablePosition pos = fxTable.getSelectionModel().getSelectedCells().get(0);
                int col = pos.getColumn();
                if (col == 0) {

                    //The code below creates the DatePicker in the cell using the DatePickerCell class that I created following the example in the code I found
                    tblDateFX.setCellFactory(new Callback<TableColumn<Map.Entry<LocalDate, Double>, String>, TableCell<Map.Entry<LocalDate, Double>, String>>() {
                        @Override
                        public TableCell<Map.Entry<LocalDate, Double>, String> call(TableColumn<Map.Entry<LocalDate, Double>, String> param) {
                            ObservableMap<LocalDate, Double> items = FXCollections.observableMap(myBasket.getEnrtriesCur(curName));

                            DatePickerCell datePick = new DatePickerCell(items);
                            return datePick;
                        }
                    });
                }
            }
        }
    });

这是DatePickerCell类

public class DatePickerCell<S, T> extends TableCell<Map.Entry<LocalDate,Double>, String> {

private DatePicker datePicker;
private ObservableMap<LocalDate,Double> curEntries;


public DatePickerCell(ObservableMap<LocalDate,Double> curEntries) {

    super();

    this.curEntries = curEntries;

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

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

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

    super.updateItem(item, empty);

    if (null == this.datePicker) {
        System.out.println("datePicker is NULL");
    }

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

        if (isEditing()) {

            setContentDisplay(ContentDisplay.TEXT_ONLY);

        } else {

            datePicker.setValue(LocalDate.parse(item,df));


            setGraphic(this.datePicker);
            setText(item);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

        }
    }
}

@Override
public void startEdit() {
    super.startEdit();
}

@Override
public void cancelEdit() {
    super.cancelEdit();
    setContentDisplay(ContentDisplay.TEXT_ONLY);
    setGraphic(null);
}


private void createDatePicker() {
    this.datePicker = new DatePicker();
    datePicker.setEditable(true);

    datePicker.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            setGraphic(datePicker);
            setText(df.format(datePicker.getValue()));
        }
    });

    datePicker.setOnAction(new EventHandler() {
        public void handle(Event t) {
            LocalDate date = datePicker.getValue();
            int index = getIndex();

            commitEdit(df.format(date));

            if (null != getCurEntries()) {
                System.out.println("Modify value");

            }
        }
    });

    setAlignment(Pos.CENTER);
}

2 个答案:

答案 0 :(得分:0)

您是否尝试过函数setOnEditCommit来反转代码?

import { Directive,HostListener } from '@angular/core';

@Directive({
  selector: '[appToUpperCase]'
})
export class ToUpperCaseDirective {

  constructor() { }

  @HostListener('keydown', ['$event']) onKeyDown(event:KeyboardEvent) {
    if (event.keyCode>32 && event.keyCode<128)
   {
      event.target['value']+=event.key.toUpperCase();
      event.preventDefault(); //stop propagation
      //must create a "input" event, if not, there are no change in your value
      var evt = document.createEvent("HTMLEvents");
      evt.initEvent("input", false, true);
      event.target.dispatchEvent(evt);
    }

  }

}

答案 1 :(得分:0)

经过一番研究后,我发现TableView中单元格的默认呈现是一个标签。因此,我调整了DatePickerCell类以在“updateItem”方法中呈现标签,并仅在单击标签时呈现DatePicker(意味着用户想要编辑单元格中的日期)。

在“返回”方面,我在DatePicker上添加了一个“ESC keypressed”的监听器,因此当按下该键时(在编辑期间),将呈现标签并因此取消编辑。这很有效!

当用户尝试通过点击屏幕上的其他位置来取消编辑时,我仍在试图弄清楚如何做同样的事情。

-

所以这是我对DatePickerEdit类的抨击。

这就是我需要的。只有当用户单击日期单元格时才会呈现单元格,只有当用户点击日期单元格时才会呈现单元格。如果用户点击单元格,单元格将返回其初始渲染(在编辑时按下“ESC”或者确实选择新日期时也会发生相同的情况)。

请注意,我将Observable列表传递给包含TableView中显示的值的Observable列表。通过这种方式,我可以直接在类中更新列表中的值。不确定这是不是一个好的做法,但这是一个“强制解决方案”。最初我对TableColumn使用了“setOnEditCommit”方法,但经过一些测试后,我注意到在更新单元格后并不总是调用此事件(即为单元格调用了commitEdit()方法)。不确定这是一个错误还是我的代码有问题。当然,它并不总是发生。在多次运行中,我会说三分之一显示出这种错误行为。

这是代码,不确定它是否是“好”代码。我很感激任何建议。

public class DatePickerCell<S, T> extends TableCell<FX, String> {

    private DatePicker datePicker;
    private Label lbl;
    private ObservableList<FX> currencies;


    public DatePickerCell(ObservableList<FX> list) {

        super();

        lbl=new Label();
        this.currencies=list;
        if (datePicker == null) {
            createDatePicker();
        }

    }

    @Override
    public void updateItem(String item, boolean empty) {
//        This section here manages the graphic rendering of each cell
//        As I don't want to generate the datepicker graphics immediately I just render a label
        super.updateItem(item, empty);

        if (empty || item == null) {
            setText(null);
            setGraphic(null);
        } else {
            createLabel(item);
        }
    }

    @Override
    public void startEdit() {
        super.startEdit();
    }

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

    private void createDatePicker() {
        this.datePicker = new DatePicker();
        datePicker.setEditable(true);

//        when the user clicks on the label the DatePicker graphics is generated
        lbl.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {

                datePicker.setValue(LocalDate.parse(lbl.getText(),df));
                setGraphic(datePicker);
                setText(lbl.getText());
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                datePicker.requestFocus();
            }
        });


//       This listener manages the "lost focus" on the picker
        datePicker.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
//                This combination of OldValue NewValue is generated whenever there is a click outside the DatePicker "graphic area"
//                i.e. the calendar (when open), the text filed, the calendar icon OR when a NEW date is selected in the calendar.
//                 This last case generates the "OnAction" event as well that is managed below.
                if (oldValue && !newValue) {
                    createLabel(df.format(datePicker.getValue()));
                }
            }
        });

//        This is generated when a NEW date is picked
//        it simply commits the new date and changes the graphics back to a label
        datePicker.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                LocalDate date = datePicker.getValue();
                int index=getIndex();

                if (date!=null) {
                    commitEdit(df.format(date));
                    getCurrencies().get(index).setDate(date);
                    createLabel(df.format(date));
                }
            }
        });

//        added this listener in case the user wants to cancel pressing "ESC"
//        when this happens the label graphics is rendered
        datePicker.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                LocalDate date = datePicker.getValue();
                if (event.getCode()== KeyCode.ESCAPE) {
                    createLabel(df.format(date));
                }
            }
        });

        setAlignment(Pos.CENTER_LEFT);
    }

    private void createLabel(String item) {
        lbl.setMinWidth(getWidth());
        setGraphic(lbl);
        lbl.setText(item);
    }

    public ObservableList<FX> getCurrencies() {
        return currencies;
    }
}