JClass LiveTable

PreviousNextIndex

7

Events and Listeners

Displaying Cells  Editing Cells  Painting Tables  Printing Tables  Resizing Cells

Scrolling in Tables  Selecting Cells  Sorting Table Data  Table Data Changes  Traversing Cells

The following sections explain how to generate and receive events in your JClass LiveTable programs.

The descriptions are listed in sets of events and event listeners, with examples of when you would use the event and listener, and sample code.

In order to register an event listener in your program, it must implement the listener's interface.


7.1 Displaying Cells

JCCellDisplayEvent

This event is posted for every cell that is displayed in the table. When you receive a JCCellDisplayEvent object, you can call following methods:

A display request from JCTable generates a JCCellDisplayEvent and notifies any JCCellDisplayListeners that they can customize the display object by calling setDisplayData() on the event. JCTable does not generate the event if there are no listeners registered with the table.

JCCellDisplayListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCCellDisplayListener interface):

  table.addCellDisplayListener(this);

JCCellDisplayListener requires the following method to be implemented:

  public void cellDisplay(JCCellDisplayEvent e)

Calling JCCellDisplayEvent and JCCellDisplayListener methods

JCCellDisplayListener's method is called before each cell is rendered, and all JCCellDisplayEvent methods are available at all times during the display process. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCCellDisplay Events and Listeners

JCCellDisplayListener can be used to format the display String. Changing displayed data does not affect either data source values or values passed to editors. As such, JCCellDisplayEvent does not provide any mechanism to store the displayed data in the data source. The following example (see examples/table/listeners/BooleanDisplay.java) displays objects as yes/no. Setting the display object does not have any effect during edit.

Figure 14 :  Using JCCellDisplayEvent to display BooleanCellData objects as yes/no Strings.

import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.table.JCCellDisplayListener;
import com.klg.jclass.table.JCCellDisplayEvent;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;

public class BooleanDisplay extends JPanel implements JCCellDisplayListener {

// Table instance
protected JCTable table;

// Editable table data source
protected JCEditableVectorDataSource evds;

public BooleanDisplay() {
  setBackground(Color.lightGray);

  // Create table instance
  table = new JCTable();

  // Create and set up data source
  evds = new JCEditableVectorDataSource();
  evds.setNumRows(2);
  evds.setNumColumns(2);
  evds.setColumnLabel(0, "Original");
  evds.setColumnLabel(1, "Formatted");
  // Note that BooleanCellEditor will be automatically chosen by Table
  evds.setCell(0, 0, new Boolean(false));
  evds.setCell(0, 1, new Boolean(false));
  evds.setCell(1, 0, new Boolean(true));
  evds.setCell(1, 1, new Boolean(true));

  // Connect table data source
  table.setDataSource(evds);

  // Turn off row labels because they are ugly.
  table.setRowLabelDisplay(false);

  // Add everything to the panel
  setLayout(new GridLayout(1,1));
add(table);

  // Add cell display listener.
  table.addCellDisplayListener(this);
}

public void cellDisplay(JCCellDisplayEvent e) {
  if(e.getColumn() == 1 && e.getRow() != JCTableEnum.LABEL) {
    // Grab displayed data, in this case a boolean
    Boolean dd = (Boolean)e.getDisplayData();
    if(dd.equals(Boolean.TRUE)) {
      e.setDisplayData("yes");
    }
    else {
      e.setDisplayData("no");
    }
  }
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("BooleanDisplay");
  BooleanDisplay bd = new BooleanDisplay();
  frame.getContentPane().add(bd);
  frame.pack();
  frame.setVisible(true);
}
}

7.2 Editing Cells

JCEditCellEvent

This event is posted whenever a user traverses into and edits a cell. When you receive a JCEditCellEvent object, you can call the following methods:

JCEditCellListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCEditCellListener interface):

  table.addEditCellListener(this);

JCEditCellListener requires the following methods to be implemented:

  public void beforeEditCell(JCEnterCellEvent e)
  public void editCell(JCEnterCellEvent e)
  public void afterEditCell(JCEnterCellEvent e)

Calling JCCellDisplayEvent and JCCellDisplayListener methods

JCEditCellListener's beforeEditCell() method is used before any cell edits by the user occur. This is the only time an edit can be cancelled. editCell() is used when the editor is displayed to the user, and at this point, you cannot cancel the edit.

Once the user's edit action has been completed, afterEditCell() is used, committing the final changes on your part. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCEditCell Events and Listeners

The following example (see examples/table/listeners/EditCell.java) displays a status comment whenever a user edits a cell.

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCEditCellListener;
import com.klg.jclass.table.JCEditCellEvent;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;

public class EditCell extends JPanel implements JCEditCellListener {

// Table instance
protected JCTable table;

// Editable data source for table
protected JCEditableVectorDataSource evds;

// Label to track table column #
protected JLabel message;

// Messages to appear in the JLabel.
protected String messages[] = {
  "This is the first column",
  "This is the second column",
  "This is the third column",
  "This is the forth column" };

public EditCell() {
  setBackground(Color.lightGray);

  // Create table instance
  table = new JCTable();

  // Create and set up data source
  evds = new JCEditableVectorDataSource();
  evds.setNumRows(10);
  evds.setNumColumns(4);
  evds.setColumnLabel(0, "First");
  evds.setColumnLabel(1, "Second");
  evds.setColumnLabel(2, "Third");
  evds.setColumnLabel(3, "Forth");
  for(int r = 0; r < evds.getNumRows(); r++)
    for(int c = 0; c < evds.getNumColumns(); c++)
      evds.setCell(r, c, "R"+r+"C"+c);

  // Connect table data source
  table.setDataSource(evds);

  // Turn off row labels because they are ugly
  table.setRowLabelDisplay(false);
  
  // Add everything to the panel
  this.setLayout(new BorderLayout());
  this.add("North", table);
  this.add("South", message = new JLabel());

  // Add cell Edit event listener
  table.addEditCellListener(this);
}

public void beforeEditCell(JCEditCellEvent event) {
  message.setText(messages[event.getColumn()]);
}

public void editCell(JCEditCellEvent event) {
  // get the editing component and select all of the text if it
  // is a JTextField component
  Component c = event.getEditingComponent();
  if(c instanceof JTextField) {
    ((JTextField)c).selectAll();
  }
}
public void afterEditCell(JCEditCellEvent event) {
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("EditCell");
EditCell ec = new EditCell();
  frame.getContentPane().add(ec);
  frame.pack();
  frame.setVisible(true);
}
}

7.3 Painting Tables

JCPaintEvent

This event is posted before and after a portion of the table is painted. When you receive a JCPaintEvent object, you can call the following methods:

JCPaintListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCPaintListener interface):

  table.addPaintListener(this);

JCPaintListener requires the following methods to be implemented:

  public void beforePaint(JCPaintEvent e)
  public void afterPaint(JCPaintEvent e)

Calling JCPaintEvent and JCPaintListener Methods

JCPaintListener's methods, beforePaint() and afterPaint(), can call JCPaintEvent methods at any time, as you are not able to interrupt the cell painting process. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCPaint Events and Listeners

JCPaintListener allows you to monitor the repainting of table cells. Labels, frozen cells, and scrollable cells are painted independently.


7.4 Printing Tables

JCPrintEvent

This event is posted when your table is printed. When you receive a JCPrintEvent object, you can call the following methods:

JCPrintListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCPrintListener interface):

  table.addPrintListener(this);

JCPrintListener requires the following methods to be implemented:

  public void printPageHeader(JCPrintEvent e)
  public void printPageFooter(JCPrintEvent e)
  public void printPageBody(JCPrintEvent e)

Using JCPrint Events and Listeners

JCPrintListener allows you to customize the header and footer regions for each page of the printout. Table Printing, in Chapter 8, has details and examples for using the JCPrintListener.


7.5 Resizing Cells

JCResizeCellEvent

This event is posted when a cell or label is resized. When you receive a JCResizeCellEvent object, you can call the following methods:

JCResizeCellListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCResizeCellListener interface):

  table.addResizeCellListener(this);

JCResizeCellListener requires the following methods to be implemented:

  public void beforeResizeCell(JCResizeCellEvent e)
  public void resizeCell(JCResizeCellEvent e)
  public void afterResizeCell(JCResizeCellEvent e)

JCResizeCellMotionListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCResizeCellMotionListener interface):

  table.addResizeCellMotionListener(this);

JCResizeCellMotionListener requires the following methods to be implemented:

  public void resizeCellDragged(JCResizeCellEvent e)

Calling JCResizeCellEvent and JCResizeCellListener Methods

JCResizeCellListener's beforeResizeCell() method is called once cell resizing begins, and allows the opportunity to programmatically cancel the resize. resizeCell() is called once the user releases the mouse button, and the resize is complete from their perspective. Programmatically, you can cancel the resize, or set new column widths or row heights if the cell resize dimension is invalid, or outside the boundaries of predefined maximum/minimum cell sizes.

Once the resize values have been set, afterResizeCell() is used, committing the final resize changes. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCResizeCell Events and Listeners

JCResizeCellListener allows you to customize how table resizes on a per-cell basis. The following example (see examples/table/listeners/ResizeCell.java) restricts resize so that row labels cannot be resized and no cell can be less than 100 pixels or greater than 200 pixels.

import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.table.JCResizeCellListener;
import com.klg.jclass.table.JCResizeCellMotionListener;
import com.klg.jclass.table.JCResizeCellEvent;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;

public class ResizeCell extends JPanel implements JCResizeCellListener,
                  JCResizeCellMotionListener {


// Table instance
protected JCTable table;

// Editable table data source
protected JCEditableVectorDataSource evds;

public ResizeCell() {
  setBackground(Color.lightGray);

  // Create table instance
  table = new JCTable();

  // Create and set up data source
  evds = new JCEditableVectorDataSource();
  evds.setNumRows(100);
  evds.setNumColumns(2);

  evds.setColumnLabel(0, "End-Point");
  evds.setColumnLabel(1, "Drag");

  for(int r = 0; r < evds.getNumRows(); r++) {
    evds.setRowLabel(r, "Row: "+r);
    for(int c = 0; c < evds.getNumColumns(); c++) evds.setCell(r,c,"Cell: R"+r+"C"+c);
  }
  // Connect table data source
  table.setDataSource(evds);

  // Add everything to the panel
  this.setLayout(new GridLayout(1,1));
  this.add(table);

  // Add resize cell listener
  table.addResizeCellListener(this);
  // Add resize cell motion listener
  table.addResizeCellMotionListener(this);
}

public void beforeResizeCell(JCResizeCellEvent event) {
  if (event.getColumn() == JCTableEnum.LABEL) {
    event.setCancelled(true);
    return;
  }
}

public void resizeCell(JCResizeCellEvent event) {
  // Width must be between 100 and 200
  int width = event.getNewColumnWidth();
  if (width < 100) {
    event.setNewColumnWidth(100);
  }
  else if (width > 200) {
    event.setNewColumnWidth(200);
  }

  // Height must be between 30 and 70
  int height = event.getNewRowHeight();
  if (height != JCTableEnum.NOVALUE && height < 30) {
    event.setNewRowHeight(30);
  }
  else if (height > 70) {
    event.setNewRowHeight(70);
  }
}

public void afterResizeCell(JCResizeCellEvent event) {
}

public void resizeCellDragged(JCResizeCellEvent event) {
  // restrict the range of motion for column 1 to 100 to 200
  if(event.getColumn() == 1) {
    int width = event.getNewColumnWidth();
    if(width < 100) {
      event.setNewColumnWidth(100);
    }
    else if(width > 200) {
      event.setNewColumnWidth(200);
    }
  }
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("ResizeCell");
  ResizeCell rc = new ResizeCell();
  frame.getContentPane().add(rc);
  frame.pack();
  frame.setSize(600, 400);
  frame.setVisible(true);
}
}

7.6 Scrolling in Tables

JCScrollEvent

This event is posted when the table is scrolled by either the user or the application. When you receive a JCScrollListener object, you can call the following methods:

The JCScrollListener (registered with addScrollListener(JCScrollListener)) allows you to define a procedure to be called when the table scrolls; this is useful if your application is drawing into the table. The method is sent an instance of JCScrollEvent.

JCScrollListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCScrollListener interface):

table.addScrollListener(this);

JCScrollListener requires the following methods to be implemented:

public void scroll(JCScrollEvent e)
public void afterScroll(JCScrollEvent e)

Calling JCScrollEvent and JCScrollListener Methods

JCScrollListener's scroll() method is invoked when the user begins to scroll, during which all JCScrollEvent methods are available. afterScroll() is called when the user has finished scrolling. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCScroll Events and Listeners

JCScrollListener allows you to synchronize table scrolling with another object. The following example (see examples/table/listeners/TwoTables.java) links two tables together with one scrollbar. This example uses two tables inside another table to simulate a splitter window.

Figure 15 :  Example using JCScrollListener to synchronize scrolling between two tables.

import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCVectorDataSource;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.table.JCScrollListener;
import com.klg.jclass.table.JCScrollEvent;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Adjustable;
import java.awt.Component;
import java.awt.Scrollbar;
import javax.swing.JPanel;

public class TwoTables extends JPanel implements JCScrollListener {

// First table
protected JCTable table1;

// Second table
protected JCTable table2;

// Common data source
protected JCEditableVectorDataSource evds1;

// Local variable used to avoid infinite loops in
// scroll event handler
protected boolean forcedScroll = false;

public TwoTables() {
  setBackground(Color.lightGray);

  // Create first table
  table1 = new JCTable();

  // Create and set up data source for first table
  evds1 = new JCEditableVectorDataSource();
  evds1.setNumRows(100);
  evds1.setNumColumns(6);

  for (int c = 0; c < evds1.getNumColumns(); c++)
    evds1.setColumnLabel(c, "C"+c);
  for (int r = 0; r < evds1.getNumRows(); r++) {
    evds1.setRowLabel(r, "R"+r);
    for (int c = 0; c < evds1.getNumColumns(); c++)
      evds1.setCell(r,c,"R"+r+"C"+c);
  }

  // Connect data source to first table.
  table1.setDataSource(evds1);

  // Set up visuals and interactions for table 1.
  table1.setAllowCellResize(JCTableEnum.RESIZE_NONE);
  table1.setHorizSBDisplay(JCTableEnum.SBDISPLAY_NEVER);
  table1.getDefaultCellStyle().setTraversable(false);
  table1.setVisibleRows(2);
  table1.setVisibleColumns(3);

  // Create second table
  table2 = new JCTable();

  // Connect second table to same data source as first table.
  table2.setDataSource(evds1);

  // Set up visuals and interactions for table 2.
  table2.setAllowCellResize(JCTableEnum.RESIZE_NONE);
  table2.setColumnLabelDisplay(false);
  table2.setTopRow(2);
  table2.getDefaultCellStyle().setTraversable(false);
  table2.setVisibleRows(5);
  table2.setVisibleColumns(3);

  // Add to panel
  setLayout(new GridLayout(2,1));
  add(table1);
  add(table2);

  // Add scroll listeners for both tables
  table1.addScrollListener(this);
  table2.addScrollListener(this);

}

public void scroll(JCScrollEvent event) {
  // use forcedScroll to prevent an infinite loop, since
  // calling setValue() on the scrollbar will generate another
  // event.
  if (event.getDirection() == Scrollbar.HORIZONTAL) {
    if (forcedScroll == false) {
      // Scroll event not forced by this method, okay
      // to continue

      // Grab adjustable object
      Adjustable adj = event.getAdjustable();
      // We need for it to be a component. Should be -
      // scroll events come from LiveTable's scrollbar
      if (adj != null && adj instanceof Component) {
        Component c = (Component)adj;  
        if (c.getParent() == table2) {
          // If table 2 scrolled, synchronize table 2
          forcedScroll = true;
          table1.getHorizSB().setValue(event.getValue());
        }
        else if (c.getParent() == table1) {
          // If table 1 scrolled, synchronize table 2
          forcedScroll = true;
          table2.getHorizSB().setValue(event.getValue());
        }
      }
    } else {
      forcedScroll = false;
    }
  }
}

public void afterScroll(JCScrollEvent event) {
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("TwoTables");
  TwoTables tt = new TwoTables();
  frame.getContentPane().add(tt);
  frame.pack();
  frame.setVisible(true);
}

}

7.7 Selecting Cells

This event is posted when the user selects cells, or cells are selected programmatically. When you receive a JCSelectEvent object, you can call the following methods:

JCSelectListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCSelectListener interface):

table.addSelectListener(this);

JCSelectListener requires the following methods to be implemented:

  public void beforeSelect(JCSelectEvent e)
  public void select(JCSelectEvent e)
  public void afterSelect(JCSelectEvent e)

Calling JCSelectEvent and JCSelectListener Methods

JCSelectListener's methods are called when the user begins cell selection in a table. beforeSelect() is invoked when the user selects or deselects a cell, and all JCSelectEvent methods are available. For example, it is possible to cancel a selection in beforeSelect() by calling setCancelled(true).

The select() and afterSelect() methods are called during and after the selection process, meaning that at that point, the cell is now visually selected from the user's perspective. For more information, please refer to Appendix A, which provides a complete event summary.

Using JCSelect Events and Listeners

JCSelectListener allows you to monitor scrolling actions in your table, either before or after the scrolling event. The following example (see examples/table/listeners/SelectListener.java) demonstrates the use of JCSelectListener notifications to cancel out cell selection.

import java.awt.Color;
import java.awt.GridLayout;
import java.applet.Applet;
import javax.swing.JPanel;
import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCSelectListener;
import com.klg.jclass.table.JCSelectEvent;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCVectorDataSource;
import com.klg.jclass.util.swing.JCExitFrame;

public class SelectListener extends JPanel implements JCSelectListener {
// Table instance
protected JCTable table;

// Table data source
protected JCVectorDataSource ds;

public SelectListener() {
  setBackground(Color.lightGray);

// Create table instance
  table = new JCTable();
// Create and set up data source
  ds = new JCVectorDataSource();
  ds.setNumRows(10);
  ds.setNumColumns(4);

  for(int c = 0; c < ds.getNumColumns(); c++)
    ds.setColumnLabel(c, "Column: "+c);

  ds.setColumnLabel(1, "Non Selectable Column");
  for(int r = 0; r < ds.getNumRows(); r++) {
    ds.setRowLabel(r, "Row: "+r);
    for(int c = 0; c < ds.getNumColumns(); c++)
      ds.setCell(r,c,"Cell: R"+r+"C"+c);
  }

  // Connect table data source
  table.setDataSource(ds);
table.setSelectionPolicy(JCTableEnum.SELECT_RANGE);

  // Add everything to the panel
  setLayout(new GridLayout(1,1));
  add(table);

  table.addSelectListener(this);
}

public void beforeSelect(JCSelectEvent e) {
if (e.getStartColumn() == 1) {
e.setCancelled(true);
System.out.println("We don't want selection starting from this column");
return;
}
System.out.println("beforeSelect: startRow="+e.getStartRow()+
", startColumn="+e.getStartColumn());
}

public void select(JCSelectEvent e) {
if (e.getAction() == JCSelectEvent.EXTEND &&
Math.abs(e.getStartRow()-e.getEndRow())>1) {
e.setCancelled(true);
System.out.println("We don't want selection extending for more than 2 rows");
return;
}
System.out.println("select: startRow="+e.getStartRow()+
", startColumn="+e.getStartColumn()+", endRow="+e.getEndRow()+
", endColumn="+e.getEndColumn());
}

public void afterSelect(JCSelectEvent e) {
System.out.println("afterSelect: startRow="+e.getStartRow()+
", startColumn="+e.getStartColumn()+", endRow="+e.getEndRow()+
", endColumn="+e.getEndColumn());
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("SelectListener");
  SelectListener sn = new SelectListener();
  frame.getContentPane().add(sn);
  frame.pack();
  frame.setSize(600, 150);
  frame.setVisible(true);
}
}

7.8 Sorting Table Data

JCSortEvent

This event is posted when the table is sorted. When you receive a JCSortEvent object, you can call the following methods:

JCSortListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCSortListener interface):

  table.addSortListener(this);

JCSortListener requires the following method to be implemented:

  public void sort(JCSortEvent e)

Using JCSort Events and Listeners

JCSortListener allows you to synchronize the sorted rows with another object (or to sort the data source). The following example (see examples/table/listeners/Sorter.java) uses the row sort array to pull out the top value.

Figure 16 :  Sorter.java, illustrating how to use JCSort Events and Listeners.

import javax.swing.JLabel;
import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCEditableVectorDataSource;
import com.klg.jclass.table.JCSortListener;
import com.klg.jclass.table.JCSortEvent;
import com.klg.jclass.table.MouseActionInitiator;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.BorderLayout;
import javax.swing.JPanel;

public class Sorter extends JPanel implements JCSortListener {

// Table instance
protected JCTable table;

// Table data source
protected JCEditableVectorDataSource ds;

// Label that will display column top value
protected JLabel topItem;

public Sorter() {
  setBackground(Color.lightGray);

  // Create table instance
  table = new JCTable();

  // Create and set up data source
  ds = new JCEditableVectorDataSource();
  ds.setNumRows(5);
  ds.setNumColumns(2);

  // Column labels
  ds.setColumnLabel(0, "INTEGER");
  ds.setColumnLabel(1, "STRING");

  // Populate data source with generated data.
  int numrows = ds.getNumRows();
  for(int r = 0; r < numrows; r++) {
    ds.setCell(r, 0, new Integer(r+8));
    ds.setCell(r, 1, "" + (r+8));
  }

  // Connect table data source
  table.setDataSource(ds);

  // Turn off row labels because they are ugly.
  table.setRowLabelDisplay(false);

  // Allow column sorting using a shift-click combination
  table.addAction(new MouseActionInitiator(MouseActionInitiator.ANY_BUTTON_MASK, InputEvent.SHIFT_MASK), JCTableEnum.COLUMN_SORT_ACTION);

  // Add everything to the panel
  setLayout(new BorderLayout());
add(table, BorderLayout.CENTER);
  add(topItem = new JLabel("Shift-click the label to sort numeric or string data"),
    BorderLayout.SOUTH);

  // Add sort listener
  table.addSortListener(this);
}

public void sort(JCSortEvent event) {
  int columns[] = event.getColumns();
  int rows[] = event.getNewRows();
  topItem.setText("The first item in the " +
          ds.getTableColumnLabel(columns[0]) + " column is " +
          ds.getTableDataItem(rows[0],columns[0]));
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("Sorter");
  Sorter s = new Sorter();
  frame.getContentPane().add(s);
  frame.pack();
  frame.setVisible(true);
}

}

7.9 Table Data Changes

JCTableDataEvent

Unlike previous events, JCTableDataEvent objects are not thrown by JCTable; instead, they come from the table's data source. This event is posted when the TableDataModel object has been modified. When you receive a JCTableDataEvent object, you can call the following methods:

JCTableDataListener

To register the above event listener routine, use the following call (where (this) refers to the class MyClass, which implements the JCTableDataListener interface):

  table.addTableDataListener(this);

JCDataTableListener requires the following method to be implemented:

  public void dataChanged(JCTableDataEvent e)

Using JCTableData Events and Listeners

JCTableDataListener allows you to monitor any changes made to the TableDataModel object. Valid changes are listed above with the getCommand() method.

There are examples included with your JClass LiveTable distribution that demonstrate the use of data with a table. See Creating your own Data Sources, in Chapter 3, to see descriptions of the included sample code.


7.10 Traversing Cells

JCTraverseCellEvent

This event is posted when cells in the table are traversed. When you receive a JCTraverseCellEvent object, you can call the following methods:

JCTraverseCellListener

To register the above event listener routine, use the following call (where (this) refers to the class, which implements the JCTraverseCellListener interface):

  table.addTraverseCellListener(this);

JCTraverseCellListener requires the following methods to be implemented:

  public void traverseCell(JCTraverseCellEvent e)
  public void afterTraverseCell(JCTraverseCellEvent e)

Calling JCTraverseCellEvent and JCTraverseCellListener Methods

JCTraverseCellListener's traverse() method is invoked when the user begins to traverse to a neighboring cell. Since this method is called before the actual traversal, all JCTraverseCellEvent methods are available. For example, if setCancelled() is called, and is set to true, the cell traversal is cancelled. You can also call methods that permit cell skipping during traversal.

afterTraverseCell() is invoked after valid cell traversal. The setNextRow(), setNextColumn(), and setCancelled() methods are unavailable during afterTraverseCell(). For more information, please refer to Appendix A, which provides a complete event summary.

Using JCTraverse Events and Listeners

JCTraverseCellListener allows you to control how cell traversal occurs in JClass LiveTable. The following example (see examples/table/listeners/SkipNavigation.java) uses a JCTraverseCellListener to skip the second column if navigating from the first column. The column is not skipped if navigating from the third column.

import com.klg.jclass.table.JCTable;
import com.klg.jclass.table.JCTableEnum;
import com.klg.jclass.table.data.JCVectorDataSource;
import com.klg.jclass.table.JCTraverseCellListener;
import com.klg.jclass.table.JCTraverseCellEvent;
import com.klg.jclass.util.swing.JCExitFrame;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;

public class SkipNavigation extends JPanel implements JCTraverseCellListener {

// Table instance
protected JCTable table;

// Table data source
protected JCVectorDataSource ds;

public SkipNavigation() {
  setBackground(Color.lightGray);

  // Create table instance
  table = new JCTable();

  // Create and set up data source
  ds = new JCVectorDataSource();
  ds.setNumRows(10);
  ds.setNumColumns(4);

  for(int c = 0; c < ds.getNumColumns(); c++)
    ds.setColumnLabel(c, "Column: "+c);

  ds.setColumnLabel(1, "Skip from 0 to 2");
  for(int r = 0; r < ds.getNumRows(); r++) {
    ds.setRowLabel(r, "Row: "+r);
    for(int c = 0; c < ds.getNumColumns(); c++)
      ds.setCell(r,c,"Cell: R"+r+"C"+c);
  }

  // Connect table data source
  table.setDataSource(ds);

  // Add everything to the panel
  setLayout(new GridLayout(1,1));
  add(table);

  // Add traverse cell listener
  table.addTraverseCellListener(this);
}

public void traverseCell(JCTraverseCellEvent event) {
  // Skip second column when approaching from the left
  if (event.getColumn() == 0 && event.getNextColumn() == 1) {
    event.setNextColumn(2);
  }

  // Skip second column in both directions.
  //   if(event.getNextColumn() == 1)
  //   event.setNextColumn(1 + event.getNextColumn() - event.getColumn());
}

public void afterTraverseCell(JCTraverseCellEvent e) {
}

public static void main(String args[]) {
  JCExitFrame frame = new JCExitFrame("SkipNavigation");
  SkipNavigation sn = new SkipNavigation();
  frame.getContentPane().add(sn);
  frame.pack();
  frame.setSize(600, 150);
  frame.setVisible(true);
}
}

PreviousNextIndex