如何用键盘编辑JDateChooser表格单元格



在我的Java面板中,我有一个JTable,其中两列通过自定义单元格编辑器使用包com.toedter.calendar中的JDateChooser对象。与使用文本框或其他简单组件的单元格不同,您可以在不必事先单击单元格的情况下键入这些单元格,日期选择器单元格中不存在此功能。就我目前的理解而言,这是因为我的自定义编辑器返回JDateChooser对象作为组件(通过getTableCellEditorComponent方法)。由于JDateChooser的父类是JPanel(根据API),这就是它试图编辑的内容,当然,您不能在JPanel中键入文本。当用户切换到日期选择器单元格并尝试在其中键入日期时,是否有某种方法可以检测?

附言:我确实找到了一种变通方法,请求将焦点放在日期选择器的文本字段上,但问题是你键入的第一个键没有出现在单元格中;它只是开始编辑单元格。如果可能的话,我希望它的行为,这样你就可以切换到单元格,例如,键入"1"一次,然后让"1"出现在其中,就像普通文本字段单元格一样。

显然,它在后来的版本中被删除了,API从未被删除已更改。

你说得对,我注意到API已经过时了,因为它是从1.2.1版本开始的,JCalendar的最新版本是1.4。我想他们没有时间更新API的在线版本,但随库分发的javadoc已经更新了。问题是getSpinner()不再可用,所以我之前的建议无法实现。

无论如何,我决定自己尝试使用JDateChooserDateCellEditor,我没有遇到太多麻烦,只是我遇到了和你开始在单元格中键入时相同的行为。焦点似乎转移到了JDateChooser顶级组件(正如您所说,它可能是JPanel)。因此,我使用AncestorListener API将焦点转移到日期编辑器。@camicker在这篇文章中很好地解释了这种方法。

这就是我做的:

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) {}
        });
    }
    ....
}

这里有两个关键因素:

  1. 使editor不可聚焦。这样可以避免焦点自动转移到作为其一部分的顶级容器
  2. 使用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;
    }
}
datepicker.getEditor().setEditable(true);

相关内容

  • 没有找到相关文章

最新更新