【问题标题】:How to edit JDateChooser table cell with keyboard如何使用键盘编辑 JDateChooser 表格单元格
【发布时间】:2013-12-03 15:57:50
【问题描述】:

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

附:我确实通过请求关注日期选择器的文本字段来管理一种解决方法,但问题是您键入的第一个键没有出现在单元格中;它只是开始编辑单元格。如果可能的话,我希望它的行为可以让您可以切换到单元格,例如键入一次“1”,然后在其中显示“1”,就像使用常规文本字段单元格一样。

【问题讨论】:

  • 我认为您需要自己的单元格编辑器阅读如何在tutorial
  • 我没有这个库,所以我无法测试它,但我有一个想法:尝试在 getTableCellEditorComponent() 实现中返回 dateChooser.getSpinner()。正如我从(糟糕的)API文档中了解到的那样,这应该返回用于编辑日期的JSpinner
  • 我无法在我的代码中调用 getSpinner() 方法。显然它在以后的版本中被删除了,并且 API 从未改变过。但我明白你的意思,实际上我曾尝试调用编辑器组件(在我们的例子中,是 JTextFieldDateEditor 的扩展)。然而,虽然这确实让我无需直接关注文本组件就可以输入数字,但日历按钮没有显示(该方法没有返回它),我们不能这样做。

标签: java swing jtable tablecelleditor jdatechooser


【解决方案1】:

显然它在以后的版本中被删除了,API 从来没有 改变了。

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

无论如何,我决定自己尝试使用JDateChooserDateCellEditor,并且我没有遇到太多麻烦,除非我遇到了与您开始输入时相同的行为细胞。似乎焦点转移到了JDateChooser 顶级组件(如您所说,它可能是JPanel)。所以我利用AncestorListener API 将焦点转移到日期编辑器。这种方法在@camickr 的this post 中有很好的解释。

这是我做的:

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;
    }
}

【讨论】:

  • 该解决方案确实可以帮助我仅使用键盘编辑单元格。但是,就像我最初的修复一样,它仍然不会记录输入的第一个数字,即输入为“05012014”的日期将显示为“50/12/014_”。为了解决这个问题,我想我可能必须覆盖 JDateChooser 本身并在那里添加一个侦听器。想法?
【解决方案2】:
datepicker.getEditor().setEditable(true);

【讨论】:

  • 你能说得更直白一点吗?
猜你喜欢
  • 2018-02-23
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 2014-09-04
  • 1970-01-01
  • 2016-11-21
相关资源
最近更新 更多