import java.awt.Component;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.EventObject;
import java.util.GregorianCalendar;
import java.util.Vector;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.SpinnerDateModel;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
public class Test extends JSpinner implements TableCellEditor{
public static void main( String[] args ) {
DefaultTableModel model = new DefaultTableModel( 0, 1 ){
public Class getColumnClass(int columnIndex){
return Date.class;
}
};
model.addRow( new Object[]{ new Date() } );
model.addRow( new Object[]{ new Date() } );
JTable table = new JTable();
table.setModel( model );
table.setDefaultEditor( Date.class, new Test() );
JFrame frame = new JFrame();
frame.getContentPane().add( new JScrollPane( table ));
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setBounds( 20, 20, 300, 200 );
frame.setVisible( true );
}
private SpinnerDateModel model;
private Vector listeners = new Vector();
// Standardkonstruktor
public Test(){
model = new SpinnerDateModel();
model.setCalendarField( Calendar.DAY_OF_YEAR );
setModel( model );
setEditor( new SpinnerEditor( this ) );
}
// Möglicherweise möchte jemand über Ereignisse des Editors
// informiert werden
public void addCellEditorListener(CellEditorListener l) {
listeners.add( l );
}
// Ein CellEditorListener entfernen
public void removeCellEditorListener(CellEditorListener l) {
listeners.remove( l );
}
// Gibt den aktuellen Wert des Editors zurück.
public Object getCellEditorValue() {
return model.getDate();
}
// Gibt eine Component zurück, welche auf dem JTable dargestellt wird,
// und mit der der Benutzer interagieren kann.
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
model.setValue( value );
return this;
}
// Gibt an, ob die Zelle editierbar ist. Das EventObject kann
// ein MouseEvent, ein KeyEvent oder sonst was sein.
public boolean isCellEditable(EventObject anEvent) {
return true;
}
// Gibt an, ob die Editor-Component selektiert werden muss, um
// sie zu benutzen. Diese Editor soll immer selektiert werden,
// deshalb wird hier true zurückgegeben
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
// Bricht das editieren der Zelle ab
public void cancelCellEditing() {
fireEditingCanceld();
}
// Stoppt das editieren der Zelle, sofern möglich.
// Da der JSpinner immer einen gültigen Wert anzeigt, kann auch
// jederzeit gestoppt werden (return-Wert = true)
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
// Benachrichtig alle Listener, dass das Editieren abgebrochen wurde
protected void fireEditingCanceld(){
ChangeEvent e = new ChangeEvent( this );
for( int i = 0, n = listeners.size(); i<n; i++ )
((CellEditorListener)listeners.get( i )).editingCanceled( e );
}
// Benachrichtig alle Listener, dass das Editieren beendet wurde
protected void fireEditingStopped(){
ChangeEvent e = new ChangeEvent( this );
for( int i = 0, n = listeners.size(); i<n; i++ )
((CellEditorListener)listeners.get( i )).editingStopped( e );
}
}
class SpinnerEditor extends JSpinner.DefaultEditor{
public SpinnerEditor( JSpinner spinner ) {
super(spinner);
JFormattedTextField field = getTextField();
field.setFormatterFactory( new JFormattedTextField.AbstractFormatterFactory() {
@Override
public AbstractFormatter getFormatter( JFormattedTextField tf ) {
return new DateFormater();
}
});
}
private class DateFormater extends JFormattedTextField.AbstractFormatter{
@Override
public Object stringToValue( String text ) throws ParseException {
try{
String[] parts = text.split( "," );
int year = 0, month = 0, day = 0;
for( int i = 0; i < parts.length; i++ ){
String part = parts[i].trim().toLowerCase();
if( part.startsWith( "year:" ) )
year = Integer.parseInt( part.substring( "year:".length() ).trim() );
if( part.startsWith( "month:" ) )
month = Integer.parseInt( part.substring( "month:".length() ).trim() );
if( part.startsWith( "day:" ) )
day = Integer.parseInt( part.substring( "day:".length() ).trim() );
}
GregorianCalendar calendar = new GregorianCalendar();
calendar.set( year, month-1, day );
return calendar.getTime();
}
catch( NumberFormatException ex ){
throw new ParseException( text, 0 );
}
}
@Override
public String valueToString( Object value ) throws ParseException {
Date date = (Date)value;
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime( date );
return "Year: " + calendar.get( Calendar.YEAR ) +
", Month: " + (calendar.get( Calendar.MONTH )+1) +
", Day: " + calendar.get( Calendar.DAY_OF_MONTH );
}
}
}