Reputation: 157
I've add a DatePicker to a TableView with the following class : https://code.google.com/p/javafx-filterable-table-columns/source/browse/src/main/java/thirdparty/eu/schudt/javafx/controls/calendar/DatePicker.java?r=db47db237b3342712aafb693f392d403455d5299
I use a DatePickerCell class to ovveride TableCell. The DatePicker display well in the TableView. But the updateItem method does not work well, it does not update the ObservableList.
What am I missing here? Can anyone faced same problem?
Here is my code :
import java.text.SimpleDateFormat;
import java.util.Locale;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import thirdparty.eu.schudt.javafx.controls.calendar.DatePicker;
public class DatePickerCell<S, T> extends TableCell<S, T> {
private final DatePicker datePicker;
private ObservableValue<T> ov;
public DatePickerCell() {
// Initialize the DatePicker for birthday
this.datePicker = new DatePicker(Locale.ENGLISH);
this.datePicker.setDateFormat(new SimpleDateFormat("dd/MM/yyyy"));
this.datePicker.getCalendarView().todayButtonTextProperty().set("Today");
this.datePicker.getCalendarView().setShowWeeks(false);
this.datePicker.getStylesheets().add("styles/DatePicker.css");
this.setAlignment(Pos.CENTER);
this.setGraphic(this.datePicker);
}
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
setGraphic(this.datePicker);
}
}
And the part of cellFactory in the FXController code :
@FXML
private TableColumn revueDateCol;
this.revueDateCol.setCellFactory(new Callback<TableColumn<Revue, Date>, TableCell<Revue, Date>>() {
@Override
public TableCell<Revue, Date> call(TableColumn<Revue, Date> arg0) {
return new DatePickerCell<>();
}
});
Thank for help.
I've tried to implements this way but when I scroll, the cell return to the original value. Any idea ?
public class DatePickerCell<S, T> extends TableCell<Revue, Date> {
private DatePicker datePicker;
public DatePickerCell() {
if (datePicker == null) {
createDatePicker();
}
setGraphic(datePicker);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Platform.runLater(new Runnable() {
@Override
public void run() {
datePicker.requestFocus();
}
});
}
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (datePicker != null) {
datePicker.setSelectedDate(getDate());
}
setGraphic(this.datePicker);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
private void createDatePicker() {
datePicker = new DatePicker(Locale.FRENCH);
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
datePicker.setDateFormat(formatter);
datePicker.setPromptText("jj/mm/aaaa");
datePicker.getCalendarView().todayButtonTextProperty().set("Aujourd'hui");
datePicker.getCalendarView().setShowWeeks(false);
datePicker.getStylesheets().add("/styles/datePicker.css");
datePicker.selectedDateProperty().addListener(
new ChangeListener<Date>() {
@Override
public void changed(ObservableValue<? extends Date> observable,
Date oldValue, Date newValue) {
commitEdit(newValue);
}
});
setAlignment(Pos.CENTER);
}
private Date getDate() {
return datePicker.getSelectedDate() != null ? datePicker.getSelectedDate() : getItem();
}
@Override
public void startEdit() {
super.startEdit();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
Regards,
Upvotes: 1
Views: 10534
Reputation: 157
Here's a solution that work. It uses a DatePicker and TableView control with Java 8. The blog post is available here.
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TableCell;
public class DatePickerCell<S, T> extends TableCell<BirthdayEvent, Date> {
private DatePicker datePicker;
private ObservableList<BirthdayEvent> birthdayData;
public DatePickerCell(ObservableList<BirthdayEvent> listBirthdays) {
super();
this.birthdayData = listBirthdays;
if (datePicker == null) {
createDatePicker();
}
setGraphic(datePicker);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Platform.runLater(new Runnable() {
@Override
public void run() {
datePicker.requestFocus();
}
});
}
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
SimpleDateFormat smp = new SimpleDateFormat("dd/MM/yyyy");
if (null == this.datePicker) {
System.out.println("datePicker is NULL");
}
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
setContentDisplay(ContentDisplay.TEXT_ONLY);
} else {
setDatepikerDate(smp.format(item));
setText(smp.format(item));
setGraphic(this.datePicker);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
}
private void setDatepikerDate(String dateAsStr) {
LocalDate ld = null;
int jour, mois, annee;
jour = mois = annee = 0;
try {
jour = Integer.parseInt(dateAsStr.substring(0, 2));
mois = Integer.parseInt(dateAsStr.substring(3, 5));
annee = Integer.parseInt(dateAsStr.substring(6, dateAsStr.length()));
} catch (NumberFormatException e) {
System.out.println("setDatepikerDate / unexpected error " + e);
}
ld = LocalDate.of(annee, mois, jour);
datePicker.setValue(ld);
}
private void createDatePicker() {
this.datePicker = new DatePicker();
datePicker.setPromptText("jj/mm/aaaa");
datePicker.setEditable(true);
datePicker.setOnAction(new EventHandler() {
public void handle(Event t) {
LocalDate date = datePicker.getValue();
int index = getIndex();
SimpleDateFormat smp = new SimpleDateFormat("dd/MM/yyyy");
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
cal.set(Calendar.MONTH, date.getMonthValue() - 1);
cal.set(Calendar.YEAR, date.getYear());
setText(smp.format(cal.getTime()));
commitEdit(cal.getTime());
if (null != getBirthdayData()) {
getBirthdayData().get(index).setDate(cal.getTime());
}
}
});
setAlignment(Pos.CENTER);
}
@Override
public void startEdit() {
super.startEdit();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
public ObservableList<BirthdayEvent> getBirthdayData() {
return birthdayData;
}
public void setBirthdayData(ObservableList<BirthdayEvent> birthdayData) {
this.birthdayData = birthdayData;
}
public DatePicker getDatePicker() {
return datePicker;
}
public void setDatePicker(DatePicker datePicker) {
this.datePicker = datePicker;
}
}
Upvotes: 2
Reputation: 49195
To make the tableView editable, you need to
tableView.setEditable(true)
.
override the startEdit()
, cancelEdit()
methods of TableCell
.
set the revueDateCol.setOnEditCommit()
of the related TableColumn
.
invoke commitEdit()
when editing has been finished.
The working example is official tutorial for Table View, Example 12-11: Alternative Solution Of Cell Editing.
The first three steps above are almost identical, except that you will be using DatePicker instead of TextField.
The last step can be as:
private void createTextField() {
datePicker = new DatePicker(Locale.ENGLISH);
datePicker.setDateFormat(new SimpleDateFormat("dd/MM/yyyy"));
datePicker.getCalendarView().todayButtonTextProperty().set("Today");
datePicker.getCalendarView().setShowWeeks(false);
datePicker.getStylesheets().add("styles/DatePicker.css");
datePicker.selectedDateProperty().addListener(new ChangeListener<Date>() {
@Override
public void changed(ObservableValue<? extends Date> observable, Date oldValue, Date newValue) {
commitEdit(newValue);
}
});
}
Upvotes: 0