AnsweredAssumed Answered

HOW TO: Get featureclass attributes into a JTable - Java

Question asked by ldonahue on Feb 19, 2013
I've seen a post or two about getting featureclass attributes into a .NET datagrid, now you have a sample for the Java community...  which I believe consists of myself and Eric Bader, and maybe two other people.

Checking the Java 1.6 API, a JTable can be created in a number of ways, with Object arrays, Vectors or by using a TableModel.  This sample is extending an AbstractTableModel.

JTable myTable = new JTable(new MyTableModel());

import; import javax.swing.table.AbstractTableModel;  import com.esri.arcgis.carto.FeatureLayer; import com.esri.arcgis.geodatabase.IFeatureClass; import com.esri.arcgis.geodatabase.IFeatureCursor; import com.esri.arcgis.geodatabase.IRow; import com.esri.arcgis.interop.AutomationException; import com.esri.arcgis.system.Cleaner;  public class MyTableModel extends AbstractTableModel {      private static final long serialVersionUID = whatever value you generate here;          public MyTableModel(){         data = createTableModel();     }      @Override     public int getRowCount() {         return data.length;     }      @Override     public int getColumnCount() {         return columnNames.length;     }              @Override     public String getColumnName(int column) {         return columnNames[column];     }      @Override     public Object getValueAt(int rowIndex, int columnIndex) {         return data[rowIndex][columnIndex];     }      @Override     public void setValueAt(Object aValue, int rowIndex, int columnIndex) {         data[rowIndex][columnIndex] = (String) aValue;     }          @Override     public boolean isCellEditable(int rowIndex, int columnIndex) {     // Allow editing on the field named "FIELD THREE"         if (columnIndex == 3) {             return true;         } else {             return false;         }     }          private String [][] createTableModel(){                  try{                          // Get the feature layer being used as the data source to the table model.             //   Basically, this method takes a String featureclass name, iterates over the TOC to match the name, and returns a FeatureLayer             FeatureLayer fl = (FeatureLayer) MapUtility.getLayerByName(MyTableModel.FEATURELAYERNAME);             IFeatureClass featureClass = fl.getFeatureClass();                          // Passing null as a QueryFilter parameter to search will return all records.             //  Using a recycling cursor (true) improves performance, but is only intended to read data, which we are doing here.             //  Row objects returned by a recycling cursor should not be modified, which we're not.             //  You might even consider not using a featureCursor here at all, if you perform an ITable_search on your featureClass, then you could use a regular ICursor             IFeatureCursor featCursor =, true);                          int oidFieldIndex = featureClass.findField(featureClass.getOIDFieldName());             int fieldoneFieldIndex = featureClass.findField("FIELD ONE");             int fieldtwoFieldIndex = featureClass.findField("FIELD TWO");             int fieldthreeFieldIndex = featureClass.findField("FIELD THREE");                          //  We need to know how big to make the [][] array.             int featureCount = featureClass.featureCount(null);                          // Create a new String[][] with the number of records in your featureclass             data = new String [featureCount][];                              // Assign values to the data[][]             //  This gets expensive creating a new String array for every featureclass record             int i = 0;             IRow row = null;             while((row = featCursor.nextFeature()) != null){                 oid = row.getValue(oidFieldIndex).toString();                 fieldOne = row.getValue(fieldoneFieldIndex).toString();                 fieldTwo = row.getValue(fieldtwoFieldIndex).toString();                 fieldThree = row.getValue(fieldthreeFieldIndex).toString();                                  String [] x = {oid, fieldOne, fieldTwo, fieldThree};                 data[i] = x;                 i++;             }                          // If the cursor is no longer needed, release it.             Cleaner.release(featCursor);                      } catch (AutomationException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         }                  return data;     }          private String[][] data;          // I'm assuming that your featureclass has all string field types, if so, you might just consider putting the row.getValue method calls in the String [] x array directly.     private String oid = null;     private String fieldOne= null;     private String fieldTwo = null;     private String fieldThree = null;          // You can use the actual field names, or make up your own alias for the featureclass field names for the JTable column headers     private String[] columnNames = {"OID", "Alias for field one", "Alias for field two", "Alias for field three"};          private static final String FEATURELAYERNAME = "Your feature layer name here";      }