JMU
Cell Editors
in Java


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Review
Motivation
Existing Hooks
An Example

A Supporting Class

javaexamples/celleditor/Course.java
/**
 * A very simple immutable encapsulation of a Course.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class Course
{
  private String   department, number;
  
  /**
   * Explicit Value Constructor.
   * 
   * @param department The department identifier
   * @param number     The course number
   */
  public Course(String department, String number)
  {
    this.department = department;
    this.number = number;
  }
  
  /**
   * Get the department identifier.
   * 
   * @return  The department identifier
   */
  public String getDepartment()
  {
    return department;
  }
  
  /**
   * Get the Course number.
   * 
   * @return  The Course number
   */
  public String getNumber()
  {
    return number;
  }
  
  /**
   * Get a String representation of this Course.
   * 
   * @return  The String
   */
  public String toString()
  {
    return department + number;
  }
}
        
An Example (cont.)

The Component

javaexamples/celleditor/CourseField.java
import java.awt.*;
import javax.swing.*;

/**
 * A GUI Component that can be used to edit Course information.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseField extends JPanel
{
  private static final long serialVersionUID = 1L;
  private static final String[] DEPARTMENTS = {"CS", "ENG", "MATH", "PHYS"};
  
  private JComboBox<String> departmentField;
  private JTextField        numberField;
  
  /**
   * Default Constructor.
   */
  public CourseField()
  {
    super();
    departmentField = new JComboBox<String>(DEPARTMENTS);
    numberField = new JTextField();
    
    setLayout(new BorderLayout());
    add(departmentField, BorderLayout.WEST);
    add(numberField, BorderLayout.CENTER);
  }
  
  /**
   * Get a Course object from this CourseField.
   * 
   * @return A new Course object with the appropriate attributes
   */
  public Course getCourse()
  {
    int selected = departmentField.getSelectedIndex();
    return new Course(departmentField.getItemAt(selected), numberField.getText());
  }
  
  /**
   * Use the attributes of a Course object to populate this CourseField.
   * 
   * @param course  The Course object to use
   */
  public void setCourse(Course course)
  {
    departmentField.setSelectedItem(course.getDepartment());
    numberField.setText(course.getNumber());
  }
}
        
An Example (cont.)

The Editor

javaexamples/celleditor/CourseCellEditor.java
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
 * A TableCellEditor that can for Course objects.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseCellEditor extends AbstractCellEditor implements TableCellEditor
{
  private static final long serialVersionUID = 1L;

  private CourseField     field;
  
  /**
   * Default Constructor.
   */
  public CourseCellEditor()
  {
    field = new CourseField();
  }
  
  /**
   * Get the value in the TableCellEditor.
   * 
   * @return Object  The value
   */
  public Object getCellEditorValue()
  {
    return field.getCourse();
  }

  /**
   * Get the Component to use when editing a cell
   * 
   * @param table  The JTable of interest
   * @param value  The value in the cell of interest
   * @param isSelected true if the cell of interest is selected
   * @param row The row of the cell of interest
   * @param column The column of the cell of interest
   * @return The Component to use for editing
   */
  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
      int row, int column)
  {
    // Initialize the CourseField
    if ((value != null) && (value instanceof Course))
    {
      field.setCourse((Course)value);
    }

    return field;
  }

}
        
An Example (cont.)

A Model for the JTable

javaexamples/celleditor/GenericTableModel.java
import javax.swing.table.*;

/**
 * A TableModel in which each cell is editable and can be an
 * object of any class.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class GenericTableModel extends DefaultTableModel 
{
  private static final long serialVersionUID = 1L;

  private boolean[]   editable;

  /**
   * Explicit Value Constructor.
   *
   * @param data        The data in the table
   * @param columnNames The names of the columns
   */
  public GenericTableModel(Object[][] data, Object[] columnNames)
  {
    super(data, columnNames);
    editable = new boolean[columnNames.length];
    for (int i=0; i<editable.length; i++) editable[i] = true;
  }

  /*
   * Get the class associated with a particular column.
   *
   * The JTable uses this method to determine the default 
   * renderer/editor for each cell. 
   *
   * @param column   The column index
   * @return         The class associated with the given column
   */
  public Class<?> getColumnClass(int column) 
  {
    return getValueAt(0, column).getClass();
  }

  /**
   * Is a particular cell editable?
   *
   * @param row    The row number of the cell
   * @param column The column number of the cell
   * @return       true if editable and false otherwise
   */
  public boolean isCellEditable(int row, int column) 
  {
    if ((column >= 0) && (column < editable.length)) {

      return editable[column];
    }
    return false;
  }


  /**
   * Make a column editable or not
   *
   * @param column   The column index
   * @param editable true to make it editable
   */
  public void setColumnEditable(int column, boolean editable)
  {
    if ((column >= 0) && (column < this.editable.length)) {

      this.editable[column] = editable;
    }
  }
}
        
An Example (cont.)

The Application

javaexamples/celleditor/CourseCellEditorDemo.java
import java.awt.*;
import javax.swing.*;
import javax.swing.table.TableColumn;

/**
 * A demonstration of a custom TableCellEditor.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseCellEditorDemo implements Runnable
{
  /**
   * Create the GUI.
   * 
   * @param args  The command line arguments (which are ignored)
   * @throws Exception if anything goes wrong
   */
  public static void main(String[] args) throws Exception
  {
    SwingUtilities.invokeAndWait(new CourseCellEditorDemo());
  }
 
  /**
   * The code to run in the event dispatch thread.
   */
  public void run()
  {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(640, 480);
    
    JPanel contentPane = (JPanel)f.getContentPane();
    contentPane.setLayout(new BorderLayout());

    // Create the model for the JTable
    String[] columnNames = {"Courses"};
    Object[][] data = {{new Course("CS", "101")}};
    
    GenericTableModel model = new GenericTableModel(data, columnNames);
    for (int i=0; i<10; i++) model.addRow(data[0]);

    JTable table = new JTable(model);

    for (int i=0; i<columnNames.length; i++) 
    {
      TableColumn column = table.getColumn(columnNames[i]);
      column.setPreferredWidth(200);
    }
    table.setRowHeight(45);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

    // Use the default TableCellRenderer (which calls the Object's toString())
    
    // Use a custom TableCellEditor
    table.setDefaultEditor(Course.class, new CourseCellEditor());
    
    contentPane.add(new JScrollPane(table),  BorderLayout.CENTER);
    
    f.setVisible(true);
  }
}
        
An Additional Requirement of ComboBoxEditor