我有一个包含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状态?如果您需要查看我的具体代码,请告诉我。
这是检查双击然后创建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);
}
答案 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;
}
}