2013-11-19 6 views
2

В моей панели Java у меня есть JTable, в которой два из столбцов используют объект JDateChooser, из пакета com.toedter.calendar, через собственный редактор ячеек. В отличие от ячеек, которые используют текстовые поля или другие простые компоненты, которые вы можете вводить без предварительного щелчка по ячейке, эта функциональность отсутствует в ячейках выбора даты. Насколько я понимаю, это связано с тем, что мой пользовательский редактор возвращает объект JDateChooser в качестве компонента (через метод getTableCellEditorComponent). Поскольку родительский класс JDateChooser равен JPanel (according to the API), это то, что он пытается отредактировать, и, конечно же, вы не можете вводить текст в JPanel. Есть ли способ обнаружить, когда пользователь переходит к ячейке выбора даты и пытается ввести дату в нее?Как отредактировать ячейку таблицы JDateChooser с клавиатурой

P.S. Я сделал некоторое обходное решение, обратив внимание на текстовое поле выбора даты, но улов в том, что первый ключ, который вы вводите, не отображается в ячейке; он просто начинает редактирование ячейки. Если это возможно, я бы хотел, чтобы он вел себя так, чтобы вы могли перейти к ячейке, например, введите «1», например, и в нем появится «1», как и в ячейке обычного текстового поля.

+1

Я думаю, что вам нужен собственный редактор для ячейки читать, как сделать это в [Учебник] (http://docs.oracle.com /javase/tutorial/uiswing/components/table.html#editrender) – alex2410

+0

У меня нет этой библиотеки, поэтому я не могу ее протестировать, но у меня есть идея: попробуйте вернуть 'dateChooser.getSpinner()' в 'getTableCellEditorComponent () 'реализация. Как я понимаю из (плохой) документации API, это должно возвращать 'JSpinner', который используется для редактирования Даты. – dic19

+0

Мне не удалось вызвать метод getSpinner() в моем коде. По-видимому, он был удален в более поздней версии, и API никогда не менялся. Но я вижу вашу точку зрения, и на самом деле я попытался вызвать компонент редактора (в нашем случае - расширение JTextFieldDateEditor). Однако, хотя это позволяло мне вводить цифры без необходимости непосредственного сосредоточения на текстовом компоненте, кнопка календаря не отображалась (она не возвращалась методом), и мы не можем этого сделать. –

ответ

2

По-видимому, он был удален в более поздней версии и API никогда не был изменен.

Вы правы, я заметил, что API устарел, так как это от версии 1.2.1 и последняя версия JCalendar 1.4 Я думаю, что у них нет времени, чтобы обновить онлайновую версию API, но обновляется javadoc, распространяемая вместе с библиотекой. Дело в том, что getSpinner() больше не доступно, поэтому мой превиуос suggestion недоступен.

В любом случае я решил попробовать DateCellEditor, используя JDateChooser самостоятельно, и у меня не было особых проблем, чтобы заставить его работать, за исключением того, что у меня было такое же поведение, как и при вводе в ячейку. Кажется, что фокус переносится на компонент верхнего уровня JDateChooser (как вы говорите, это, вероятно, JPanel). Поэтому я использовал API AncestorListener, чтобы перенести фокус на редактор даты. Этот подход хорошо объяснен в this post by @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) {} 

     }); 
    } 

    .... 
} 

Есть два ключевых фактора здесь:

  1. Заставить editor не фокусирование. Таким образом, вы избегаете фокуса, который автоматически переносится в контейнер верхнего уровня, который является его частью.
  2. Использование API AncestorListener.

Вот полная реализация редактора клеток:

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

Право его API имеет собственный рендерер и редактор +1 – mKorbel

+0

Это решение действительно помогает мне редактировать ячейку только с клавиатуры. Однако, как и мое первоначальное исправление, он все еще не регистрирует введенную первую цифру, то есть дата, введенная как «05012014», будет отображаться как «50/12/014_». Чтобы обойти это, я думаю, что мне, возможно, придется переписать сам JDateChooser и добавить там слушателя. Мысли? –

0
datepicker.getEditor().setEditable(true); 
+0

Не могли бы вы быть более откровенными? –