Apparently it was removed in a later version and the API was never
changed.
You're right, I've noticed the API is outdated since it's from 1.2.1 version and latest version of JCalendar is 1.4 I guess they don't have time to update the online version of the API, but the javadoc distributed with the library is updated. The thing is getSpinner() is not available anymore so my previuos suggestion is unreachable.
Anyway I've decided to try a DateCellEditor
using JDateChooser
on my own and I've had not much troubles to make it work except I've experienced the same behavior as you do when you start to type in the cell. It seems like the focus is transferred to the JDateChooser
top level component (as you say it's probably a JPanel
). So I made use of the AncestorListener API to transfer the focus to the date editor. This approach is well explained in this post by @camickr.
This is what I've made:
public class DateCellEditor extends AbstractCellEditor implements TableCellEditor {
JDateChooser editor;
public DateCellEditor() {
editor = new JDateChooser();
editor.setLocale(Locale.ENGLISH);
editor.setDateFormatString("MM/dd/yyyy");
editor.setFocusable(false); // Key #1
JComponent editorComponent = (JComponent)editor.getDateEditor();
editorComponent.addAncestorListener(new AncestorListener() { // Key #2
@Override
public void ancestorAdded(AncestorEvent event) {
((JComponent)editor.getDateEditor()).requestFocusInWindow();
}
@Override
public void ancestorRemoved(AncestorEvent event) {}
@Override
public void ancestorMoved(AncestorEvent event) {}
});
}
....
}
There are two key factors here:
- Making the
editor
not focusable. This way you'll be avoiding the focus be automatically transferred to the top level container that is part of it.
- Using the
AncestorListener
API.
Here is the complete cell editor implementation:
import com.toedter.calendar.JDateChooser;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Locale;
import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.table.TableCellEditor;
public class DateCellEditor extends AbstractCellEditor implements TableCellEditor {
JDateChooser editor;
int clickCountToStart = 2;
public DateCellEditor() {
editor = new JDateChooser();
editor.setLocale(Locale.ENGLISH);
editor.setDateFormatString("MM/dd/yyyy");
editor.setFocusable(false);
JComponent editorComponent = (JComponent)editor.getDateEditor();
editorComponent.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
((JComponent)editor.getDateEditor()).requestFocusInWindow();
}
@Override
public void ancestorRemoved(AncestorEvent event) {}
@Override
public void ancestorMoved(AncestorEvent event) {}
});
}
@Override
public Object getCellEditorValue() {
return editor.getDate();
}
@Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
}
return true;
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
@Override
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
@Override
public void cancelCellEditing() {
fireEditingCanceled();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if(value instanceof java.util.Date){
editor.setDate((java.util.Date)value);
table.setRowHeight((int)editor.getPreferredSize().getHeight());
//This last one is optional. It fits the row height to the JDateChooser preferred height.
}
return editor;
}
}