显然它在以后的版本中被删除了,并且 API 从未改变过。
你是对的,我注意到API已经过时了,因为它来自 1.2.1 版本,而JCalendar的最新版本是 1.4 我猜他们没有时间更新 API 的在线版本,但是 javadoc 与库已更新。问题是getSpinner()不再可用,因此我之前的建议无法实现。
无论如何,我决定自己尝试DateCellEditor
使用JDateChooser
,并且我没有遇到太多麻烦来使它工作,除非我遇到了与您开始输入单元格时相同的行为。似乎焦点已转移到JDateChooser
顶级组件(如您所说,它可能是 a JPanel
)。所以我利用AncestorListener API 将焦点转移到日期编辑器。@camickr在这篇文章中很好地解释了这种方法。
这是我所做的:
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) {}
});
}
....
}
这里有两个关键因素:
- 使
editor
不可聚焦。这样,您将避免焦点自动转移到作为其中一部分的顶级容器。
- 使用
AncestorListener
API。
这是完整的单元格编辑器实现:
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;
}
}