editable JTable that only accepts digits in one column
I am trying to create an editable JTable that acts like a spreadsheet. The 2nd column, 揃ib #?is only supposed to accept digits. If you double click on a cell in column 2 it activates the correct DefaultCellEditor which was set to a custom JTextField. The custom JTextField is called JDigitTextField.java and only accepts digits. However if you hit enter or a arrow key and start editing column 2 you can type anything in the cell that you want. Is there anyway that I can force the JTable to always use the correct DefaultCellEditor all the time?
I know that this is alot of code, but I included it so that you could see how the JTable works. Most of the work is done in the class ResultSheetTablePanel.java. The method setUpBibNumbersColumn creates the custom DefaultCellEditor and then uses it to create a new TableColumn which the method returns.
Here is a short explanation of the classes:
ResultSheetFrame.java is a JFrame that holds the ResultSheetTablePanel. It also calls the method showFinishSheet in ResultSheetTablePanel that displays the rider list. Call this class to start the program.
ResultSheetTableModel.java is the custom table model used in the JTable. It extends AbstractTableModel.
JDigitTextField.javais the custom JTextField that only accepts digits. I extendedJTextField and implemented a KeyListener.
StaticCellEditor.java is a custom cell editor that does not allow editing. I extended AbstractCellEditor and implemented TableCellEditor to restrict editable to false.
SheetEntry.java is the data that is used by the JTable and the table model.
To compile the program cut and past the classes to their respective files. Compile the program with java 1.5 or 1.6.
To run the program type: 搄ava ResultSheetFrame?
Type any digit between 1 and 10 in any of the cells in column 2 and the riders information should show up. if you type a digit outside that range it should give you a message dialog.
Any help is much appreciated.
Thanks
Wayne Unruh
-
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.JFrame;
publicclass ResultSheetFrameextends JFrame
{
privatestaticfinallong serialVersionUID = 100;
public ResultSheetFrame ()
{
super ("Editing Help Inside a JTable" );
Container container = getContentPane ();
container.setLayout (new BorderLayout () );
ResultSheetTablePanel rstp =new ResultSheetTablePanel ();
container.add ( rstp, BorderLayout.CENTER );
this.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
this.setSize (new Dimension ( 500, 300 ) );
this.setVisible (true );
ArrayList < SheetEntry > startEntries =new ArrayList < SheetEntry > ();
startEntries.add (new SheetEntry ( 1,"Joe Smith" ) );
startEntries.add (new SheetEntry ( 2,"Amy Smith" ) );
startEntries.add (new SheetEntry ( 3,"John Smith" ) );
startEntries.add (new SheetEntry ( 4,"Bill Jones" ) );
startEntries.add (new SheetEntry ( 5,"Frank Jones" ) );
startEntries.add (new SheetEntry ( 6,"Chris Jones" ) );
startEntries.add (new SheetEntry ( 7,"Shawn Jones" ) );
startEntries.add (new SheetEntry ( 8,"Wayne Wilson" ) );
startEntries.add (new SheetEntry ( 9,"William Wilson" ) );
startEntries.add (new SheetEntry ( 10,"Jerry Wilson" ) );
rstp.showFinishSheet ( startEntries );
}
publicstaticvoid main ( String [] args )
{new ResultSheetFrame ();}
}// end of ResultSheetFrame
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
publicclass ResultSheetTablePanelextends JPanel
implements ListSelectionListener,
CellEditorListener
{
privatestaticfinallong serialVersionUID = 100;
private DefaultCellEditor bibNumberCellEditor;
private DefaultCellEditor comboBoxEditor;
privateint currentRow;
private SortedMap < Integer, SheetEntry > finishSheetEntries;
private SheetEntry previousEntry;
private JTable rsTable;
private ResultSheetTableModel rstModel;
public ResultSheetTablePanel ()
{
super (new BorderLayout () );
// create a new TreeMap in method showFinishSheet
this.finishSheetEntries =null;
ListSelectionModel lsm =null;
DefaultTableColumnModel dtcm =null;
this.rstModel =new ResultSheetTableModel ();
dtcm =new DefaultTableColumnModel ();
dtcm.addColumn ( getStaticTableColumn ( 0, SwingConstants.CENTER,
"Place" ) );
dtcm.addColumn ( setUpBibNumbersColumn ( 1, SwingConstants.CENTER,
"Bib #") );
dtcm.addColumn ( getStaticTableColumn ( 2, SwingConstants.LEFT,
"Name" ) );
dtcm.getSelectionModel ().addListSelectionListener (this );
this.rsTable =new JTable ( this.rstModel, dtcm );
this.rsTable.setRowSelectionAllowed (true );
this.rsTable.setColumnSelectionAllowed (true );
//this.resultSheetTable.setCellSelectionEnabled ( false );
// set the list selection model and add
// this to its list of ListSelectionListener's
lsm = this.rsTable.getSelectionModel ();
lsm.setSelectionMode ( ListSelectionModel.SINGLE_SELECTION );
lsm.addListSelectionListener (this );
this.add (new JScrollPane ( this.rsTable ), BorderLayout.CENTER );
}
publicvoid editingCanceled ( ChangeEvent ce )
{}
publicvoid editingStopped ( ChangeEvent ce )
{
Object source = ce.getSource ();
if ( source == this.bibNumberCellEditor )
doBibNumberEditingStopped ();
}
publicvoid showFinishSheet ( List < SheetEntry > startSheetEntries )
{
List < SheetEntry > entries =new ArrayList < SheetEntry > ();
int place = 1,
currPlace = 0,
remainder = 0;
// clear the current Result Sheet
this.rstModel.clearAll ();
this.finishSheetEntries =new TreeMap < Integer, SheetEntry > ();
for ( SheetEntry se : startSheetEntries )
{
this.finishSheetEntries.put (new Integer ( se.getBibNumber () ),
se );
if ( currPlace != 0 )
{
currPlace = se.getPlacing ();
remainder = currPlace - place;
if ( remainder > 0 )
{
while ( place < currPlace )
{
entries.add (new SheetEntry () );
place++;
}
}
entries.add ( se );
place++;
}
}
if ( entries.size () < startSheetEntries.size () )
{
remainder = startSheetEntries.size () - entries.size ();
for (int i = 0; i < remainder; i++ )
{
entries.add (new SheetEntry () );
}
}
this.rstModel.addSheetEntryList ( entries );
}
publicvoid valueChanged ( ListSelectionEvent lse )
{
ListSelectionModel lsm =null;
int selectedRow = 0,
selectedColumn = 0;
if ( ! lse.getValueIsAdjusting () )
{
lsm = this.rsTable.getColumnModel ().getSelectionModel ();
lsm.getAnchorSelectionIndex ();
lsm.getLeadSelectionIndex ();
selectedRow = this.rsTable.getSelectedRow ();
selectedColumn = this.rsTable.getSelectedColumn ();
if ( selectedRow >= 0 &&
this.rsTable.isCellEditable ( selectedRow, selectedColumn ) )
{
this.currentRow = selectedRow;
this.previousEntry = this.rstModel.getSheetEntryAt ( this.currentRow,
0 );
}
}
}
privatevoid doBibNumberEditingStopped ()
{
StringBuilder sbnrf = null,
sbdbn =null;
String bibText = null,
placeText =null;
int placeNumber = 0;
SheetEntry currEntry = null,
prevEntry =null;
Integer currBibNumber = null,
prevBibNumber =null;
bibText = this.bibNumberCellEditor.getCellEditorValue ().toString ().trim ();
prevEntry = this.previousEntry;
prevBibNumber =new Integer ( prevEntry.getBibNumber () );
if ( ! bibText.equals ("" ) )
{
currBibNumber = Integer.valueOf ( bibText );
currEntry = this.finishSheetEntries.get ( currBibNumber );
if ( currEntry !=null )
{
if ( currEntry.getPlacing () == 0 )
{
if ( prevBibNumber.intValue () != currBibNumber.intValue () )
{
placeText = ( String ) this.rstModel.getValueAt ( this.currentRow,
0 );
try
{
placeNumber = Integer.valueOf ( placeText ).intValue ();
}
catch ( NumberFormatException nfe )
{
placeNumber = 0;
}
if ( prevBibNumber.intValue () > 0 )
{
// reset previous entry placing to 0
prevEntry = this.finishSheetEntries.get ( prevBibNumber );
prevEntry.setPlacing ( 0 );
}
// set placing the place or 0
currEntry.setPlacing ( placeNumber );
this.rstModel.addSheetEntry ( this.currentRow, currEntry );
}
}
else
{
if ( prevBibNumber.intValue () != currBibNumber.intValue () )
{
sbdbn =new StringBuilder ();
sbdbn.append ("Bib number " );
sbdbn.append ( bibText );
sbdbn.append (" is already in results at placing " );
sbdbn.append ( currEntry.getPlacing () ).append ("." );
JOptionPane.showMessageDialog ( this, sbdbn.toString (),
"Dublicate Bib Number",
JOptionPane.WARNING_MESSAGE );
}
}
}
else
{
if ( prevBibNumber.intValue () > 0 )
{
// Reset the previous entry to a placing to 0
prevEntry = this.finishSheetEntries.get ( prevBibNumber );
prevEntry.setPlacing ( 0 );
}
this.rstModel.addSheetEntry ( this.currentRow,new SheetEntry () );
sbnrf =new StringBuilder ();
sbnrf.append ("No rider found with bib number " );
sbnrf.append ( bibText ).append ("." );
JOptionPane.showMessageDialog ( this, sbnrf.toString (),
"No Rider Found",
JOptionPane.WARNING_MESSAGE );
}
}
else
{
// a blank was entered
if ( prevBibNumber.intValue () > 0 )
{
// Reset the previous entry to a placing to 0
prevEntry = this.finishSheetEntries.get ( prevBibNumber );
prevEntry.setPlacing ( 0 );
// add an empty entry into the table model
this.rstModel.addSheetEntry ( this.currentRow,new SheetEntry () );
}
}
}
/**
* Returns a <CODE>TableColumn</CODE> that represents all the attributes of
* a column in a JTable that is not editable.
* @param modelIndex
*The index of the column in the model which will supply the data for
*this column in the table.
* @param alignment
*One of the following constants defined in <CODE>SwingConstants</CODE>:
*<CODE>LEFT</CODE>, <CODE>CENTER</CODE>, <CODE>RIGHT</CODE>.
* @return A <CODE>TableColumn</CODE> that represents all the attributes of
* a column in a JTable that is not editable.
*/
private TableColumn getStaticTableColumn (int modelIndex,int alignment,
String headerText )
{
TableColumn tc =null;
DefaultTableCellRenderer dtcr =new DefaultTableCellRenderer ();
dtcr.setHorizontalAlignment ( alignment );
tc =new TableColumn ( modelIndex, 75, dtcr,new StaticCellEditor () );
tc.setHeaderValue ( headerText );
return tc;
}
private TableColumn setUpBibNumbersColumn (int modelIndex,int alignment,
String headerText )
{
TableColumn tc =null;
JDigitTextField bibNumberTextField =null;
DefaultTableCellRenderer renderer =null;
bibNumberTextField =new JDigitTextField ( 3 );
bibNumberTextField.setHorizontalAlignment ( alignment );
this.bibNumberCellEditor =new DefaultCellEditor ( bibNumberTextField );
this.bibNumberCellEditor.addCellEditorListener (this );
this.bibNumberCellEditor.setClickCountToStart ( 2 );
// Set up tool tips for the status cells.
renderer =new DefaultTableCellRenderer();
renderer.setToolTipText("Enter bib number");
renderer.setHorizontalAlignment ( alignment );
tc =new TableColumn ( modelIndex, 75, renderer,
this.bibNumberCellEditor );
tc.setHeaderValue ( headerText );
return tc;
}
}// end of ResultSheetTablePanel
--
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
publicclass ResultSheetTableModelextends AbstractTableModel
{
privatestaticfinallong serialVersionUID = 100;
private List < SheetEntry > entryList;
public ResultSheetTableModel ()
{ this.entryList =new ArrayList < SheetEntry > ();}
publicvoid addSheetEntry (int rowIndex, SheetEntry entry )
{
this.entryList.set ( rowIndex, entry );
super.fireTableRowsUpdated ( rowIndex, rowIndex );
}
publicvoid addSheetEntryList ( List < SheetEntry > currEntryList )
{
SheetEntry currentEntry =null;
int size = currEntryList.size ();
for (int i = 0; i < size; i++ )
{
currentEntry = currEntryList.get ( i );
this.entryList.add ( i, currentEntry );
}
super.fireTableDataChanged ();
}
publicvoid clearAll ()
{
this.entryList.clear ();
super.fireTableDataChanged ();
}
publicint getColumnCount ()
{return 3;}
publicint getRowCount ()
{return this.entryList.size ();}
public SheetEntry getSheetEntryAt (int rowIndex,int columnIndex )
{
SheetEntry se =null;
if ( rowIndex < this.entryList.size () )
se = this.entryList.get ( rowIndex );
return se;
}
public Object getValueAt (int rowIndex,int columnIndex )
{
Object value =null;
int place = 0,
bibNumber = 0;
SheetEntry currentEntry = this.entryList.get ( rowIndex );
if ( currentEntry.getBibNumber () >= 0 )
{
switch ( columnIndex )
{
case 0:
{
place = currentEntry.getPlacing ();
value = Integer.valueOf ( place ).toString ();
break;
}
case 1:
{
bibNumber = currentEntry.getBibNumber ();
value = Integer.valueOf ( bibNumber ).toString ();
break;
}
case 2:
{
value = currentEntry.getFullName ();
break;
}
}
}
else
{
switch ( columnIndex )
{
case 0:
{
value = Integer.valueOf ( rowIndex + 1 ).toString ();
break;
}
default:
{
value ="";
break;
}
}
}
return value;
}
publicboolean isCellEditable (int row,int col )
{
boolean editable =false;
if ( col == 1 )
editable =true;
return editable;
}
}// end of ResultSheetTableModel
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JTextField;
publicclass JDigitTextFieldextends JTextFieldimplements KeyListener
{
privateint columns;
privatestaticfinallong serialVersionUID = 100;
public JDigitTextField (int columns )
{
super ( columns );
this.columns = columns;
super.addKeyListener (this );
}
publicvoid keyPressed ( KeyEvent e ){}
publicvoid keyReleased ( KeyEvent e ){}
publicvoid keyTyped ( KeyEvent event )
{
Object source = event.getSource ();
if ( source ==this )
{
char c = event.getKeyChar ();
if ( Character.isDigit ( c ) )
{
if ( super.getText ().length () < this.columns )
event.setKeyChar ( c );
else
event.consume ();
}
else
event.consume ();
}
}
}// end of JDigitTextField
import java.awt.Component;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
publicclass StaticCellEditorextends AbstractCellEditor
implements TableCellEditor
{
privatestaticfinallong serialVersionUID = 100;
public StaticCellEditor ()
{super ();}
publicboolean isCellEditable ( EventObject e )
{returnfalse;}
publicboolean shouldSelectCell ( EventObject anEvent )
{returnfalse;}
public Component getTableCellEditorComponent ( JTable table, Object value,
boolean isSelected,
int row,int column )
{returnnull;}
public Object getCellEditorValue ()
{returnnull;}
}// end of StaticCellEditor
publicclass SheetEntry
{
privateint bibNumber;
privateint placing;
private String fullName;
public SheetEntry ()
{this ( -1,"", 0 );}
public SheetEntry (int bibNumber, String fullName )
{this ( bibNumber, fullName, 0 );}
public SheetEntry (int bibNumber, String fullName,int placing )
{
this.bibNumber = bibNumber;
this.fullName = fullName;
this.placing = placing;
}
publicint getBibNumber ()
{return this.bibNumber;}
publicint getPlacing ()
{return this.placing;}
public String getFullName ()
{return this.fullName;}
publicvoid setPlacing (int placing )
{ this.placing = placing;}
}// end of SheetEntry

