3
Working with Table Data
Overview: Data Handling in JClass LiveTable Getting Data into your Table
Using Stock Data Sources Setting Stock Data Source Properties
Loading Data from an XML Source Creating your own Data Sources Dynamically Updating Data
3.1 Overview: Data Handling in JClass LiveTable
JClass LiveTable is a Java component that creates a table-formatted view of a given set of data. Data can come from many different types of sources; different applications can have different data storage needs. Since applications can generally store data more efficiently than a component, it is more practical for JClass LiveTable to use an external data object rather than storing the data internally. An external data model organizes the data in a way that is more convenient for the application, rather than for the component.
Consequently, JClass LiveTable uses a Model-View-Controller (MVC) architecture for data handling. The data in the table cells is stored in an external data source rather than the
JCTable
object itself. Either you create the data source object, or the data source can be a database. To use the latter, you need to use one of the LiveTable data-binding Beans. For more information about these Beans, please see JClass LiveTable Beans and IDEs, in Chapter 9.With LiveTable's MVC architecture, the data source object is the Model, which manages the underlying data being displayed and manipulated. The
JCTable
object acts as both the View (the object displaying the data to the user) and the Controller (the object that manipulates and modifies the data).Because the
JCTable
object and the data source are separated, you are free to use whatever data storage mechanism you want; theJCTable
object doesn't need to know anything about the mechanism itself. The MVC architecture also helps improve the performance of JClass LiveTable programs by removing the need to load all of the table's data into memory, then copy it to theJCTable
object. The data source is able to copy only the data that is currently displayed by theJCTable
object. An external data source can also manage large sets of data more efficiently than theJCTable
object can.
3.1.1 How the Table and Data Source Communicate
Between the
JCTable
object and the data source lies an object that implements theDataViewModel
and/or theSortableDataViewModel
. The default implementation in the table isTableDataView
. While most developers will never have to work with it directly, it's important to realize that theTableDataView
monitors the data source for changes and notifies theJCTable
object when they occur. Additionally, theTableDataView
has a set of translation tables that allow it to re-map rows or columns from the data source to the table. This is how JClass LiveTable can support features like column sorting and row or column swapping, where the appearance of the table changes, without manipulating the data source itself.
3.2 Getting Data into your Table
To display data in a JClass LiveTable application or applet, you need to create a data source object. Any object that implements the
TableDataModel
interface can be a data source. This can either be one of the stock data sources included with LiveTable (see Section 3.3, Using Stock Data Sources) or one of your own data sources (see Section 3.6, Creating your own Data Sources).The
public interface TableDataModel {TableDataModel
interface is as follows:
public Object getTableDataItem(int row, int column);
public int getNumRows();
public int getNumColumns();
public Object getTableRowLabel(int row);
public Object getTableColumnLabel(int column);
public void addTableDataListener(TableDataListener l);
public void removeTableDataListener(TableDataListener l);
}The primary method in the
TableDataModel
interface isgetTableDataItem()
, which retrieves the value of a specified cell. For more information on the types of cell data objects that Table understands, see Displaying and Editing Cells, in Chapter 4. In short, you can have any type of object (usually one of Integer, Double, String, or Image) in a cell.Table Size
The size of the table is also specified by the data source, using the
getNumRows()
andgetNumColumns()
methods.Row and Column Labels
If you want to display row or column labels, their values are provided using the
getTableRowLabel()
andgetTableColumnLabel()
methods. These methods return the same types of objects asgetTableDataItem()
, but labels are never editable or traversable.Data Format Detection
When using the
JCInputStream
stock data source, LiveTable automatically detects whether a data stream is in standard table or CSV format. So by default,JCInputStreamDataSource
andJCFileDataSource
attempt to determine the format of the data source. To remove this automatic detection (and the overhead it creates), set a preferred data format type.Data Source Listeners
Any time the data inside the data source changes, it should notify all of its listeners. To add and remove listeners to and from the data source, use the methods
addTableDataListener()
andremoveTableDataListener()
.
3.2.1 Making the Data Source Editable
If you want users to be able to edit the data, you must implement the
public interface EditableTableDataModel extends TableDataModel {EditableTableDataModel
interface.EditableTableDataModel
is derived fromTableDataModel
and adds one new method:setTableDataItem()
.
public boolean setTableDataItem(Object o, int row, int column);
}When the user edits a cell in the table, the cell editor validates the data (for more information about cell editing, see Displaying and Editing Cells, in Chapter 4), and passes the new data to the data source using the
setTableDataItem()
method. If the data source does not accept the value of the object (for example, if the value is invalid in some way), it will returnfalse
to indicate that the edit has been rejected. If the new value is valid, thensetTableDataItem()
will returntrue
and the data source will store the value.The setEditable() Method
You can use the
setEditable()
method, which is part of theCellStyleModel
implementation, to turn editing on and off for specific cells and ranges of cells.setEditable()
has no effect on labels, as they can never be edited. ForsetEditable(true)
to have any effect, the data source must be editable.
3.3 Using Stock Data Sources
While it isn't hard to create a data source for a table, JClass LiveTable includes several stock data sources to save you the work of writing data sources for the most common data types. The following data sources are found in the
com.klg.
jclass.table.data
package:Most of the stock data sources extend the
JCVectorDataSource
class. Please see Appendix E, JClass LiveTable Inheritance Hierarchy, for a complete hierarchy diagram that outlines the relationship between the stock data source classes.
3.3.1 JCVectorDataSource: the Data Source Workhorse
A
JCVectorDataSource
simply stores all of its data in memory using vectors. TheJCVectorDataSource
class contains methods that allow you to set individual elements, or to set all of the data in the data source from a vector or an array of objects.Since
JCVectorDataSource
implementsTableDataModel
, it can't be edited by theJCTable
object. If you want users to be able to edit the cell values through the table, you should useJCEditableVectorDataSource
. TheJCEditableVectorDataSource
class is a subclass ofJCVectorDataSource
that implements theEdtitableTableDataModel
interface model.
3.3.2 Getting Data from an Input Stream
JClass LiveTable provides the
TABLE 2 4 NOLABEL # 2 rows, 4 columnsJCInputStreamDataSource
class to read data in through a standardjava.io.InputStream
, and since it is derived fromJCVectorDataSource
, it has all of the same capabilities as aJCVectorDataSource
(see Section 3.4, Setting Stock Data Source Properties).JCInputStreamDataSource
accepts both CSV and table format data files, and items read into the data source are stored as either String or double objects. The data format for a simple table would be similar to the following (the # symbol denotes the beginning of a comment):
1 2 3 4 # row 1
1 2 3 4 # row 2If you want to include labels, the data format would be:
TABLE 3 4
'Column 1' 'Column 2' 'Column 3' 'Column 4'
'Row 1' 1 2 3 4
'Row 2' 1 4 9 16
'Row 3' 1 16 81 256The
JCInputStreamDataSource
class has the following subclasses that provide convenient constructors to create anInputStream
from various sources:
JCFileDataSource
, for reading data from a file.JCURLDataSource
, for reading data from a URL.JCAppletDataSource
, for reading data from theDATA <PARAM>
tag associated with the specified applet.
3.3.3 Getting Data from a Database
The
JCResultSetDataSource
uses a JDBC database connection and an SQL query to create a data source. TheJCResultSetDataSource
is a rudimentary implementation of a data-bound data source to demonstrate that JClass LiveTable can be used with database applications quite easily.Note: The
JCResultSetDataSource
is not a data source that can be edited; that is, it will not write to the database.JClass LiveTable also comes with data-binding Beans that allow you to bind your table to any JDBC data source. For information about the data binding Beans, please refer to Data Binding with IDEs, in Chapter 9.
3.3.4 Caching Data with JCCachedDataSource
While
JCVectorDataSource
stores its memory using vectors, theJCCachedDataSource
class stores its data in a vector of vectors.JCCachedDataSource
uses anotherTableDataModel
class to contain table cell and label information ("in between" the table and the data source). It will reference the cache first to see if the required data exists; if it does not, the call passes through to the originalTableDataModel
class, and the value is taken. When this happens, the retrieved value is also stored inJCCachedDataSource
's otherTableDataModel
class.This method saves time by creating a second instance of previously retrieved data, outside of the actual data source.
JCCachedDataSource
should only be used when theTableDataModel
'sgetTableItem
,getTableRowLabel
, and/orgetTableColumnLabel
are calculation-intensive or expensive to retrieve.Use
JCEditableCachedDataSource
to bind to an editable data source and be able to edit the cell contents.Note: A non-editable data source bound to
JCEditableCachedDataSource
will display an editor but reject all changes.
3.3.5 Using Swing TableModel Data Objects
The
JCTableModelDataSource
enables you to use any type of SwingTableModel
data object in JClass LiveTable.JCTableModelDataSource
is an editable data source.
JCTableModelDataSource
interprets and reformats theTableModel
data to the layout used by JClass LiveTable. This makes it easier to replace the Swing JTable component with JClass LiveTable because you do not have to reformat your data.When you create a
JCTableModelDataSource
, you need to pass the constructor a valid SwingTableModel
object.
3.4 Setting Stock Data Source Properties
The following properties are set using methods of the
JCVectorDataSource
class. Since the stock data sources are derived from theJCVectorDataSource
class, you can set these properties from any of the stock data sources (though all of the properties may not be applicable to the specific data source).Note: The
JCVectorDataSource
class contains properties that are not inherent to theTableDataModel
interface. If you create your own data source, you will have to produce your own methods for such operations as adding and deleting rows and columns.
3.4.1 Working with Rows and Columns
Setting the Number of Rows/Columns
The
setNumRows()
andsetNumColumns()
methods specify the number of rows and columns in the data source (default is 5 columns and 10 rows). These values do not affect the internalCellValues
Vector
of the data source. The values of theNumRows
andNumColumns
properties are updated by theaddRow()
,addColumn()
,deleteRows()
, anddeleteColumns()
methods (see below).Specifying Row and Column Labels
You can set row and column labels by calling:
setRowLabel()
andsetColumnLabel()
for individual labels.setRowLabels()
andsetColumnLabels()
for all of the labels.Column and row labels can be set as an array of Strings, or as a vector. Each element of the labels' vector may be an instance of a String, Image, Component, or other object. To clear column or row labels, call the method with a null argument.
String clabels[] = { "Name", "Address", "Phone" };
...
JCVectorDataSource vds;
vds.setColumnLabels(clabels);
getTableRowLabel()
andgetTableColumnLabel()
for individual labels.getRowLabels()
orgetColumnLabels()
for all of the labels.Adding Rows and Columns
You can insert new rows and columns into the data source using the
addColumn()
andaddRow()
methods. TheaddColumn()
method inserts a new column into the data source, shifting any cell values to the right of the insertion. TheaddRow()
method inserts a new row into the data source, shifting any cell values down.The
Object label,addColumn()
andaddRow()
methods are identical:
Vector values)
Object label,
Vector values)
- The position parameter is the initial column (or row) index, and the new columns or rows are added prior to this position. If the position is set to
JCTableEnum.MAXINT
, the column or row is added after the final existing column or row.- The label parameter refers to the column or row label. This parameter can have a null value.
- The values parameter refers to the array of objects that comprises the cell values. This parameter can have a null value.
- Both the
addColumn()
andaddRow()
methods returnfalse
if any of the parameters are invalid; if they returnfalse
, the row or column will not be added.When calling
addRow()
andaddColumn()
, note the following:
- If you do not supply values for the new cells within the method, the cells are blank. Values for the new row or column labels must be specified separately.
- The initial row or column index cannot be greater than the values of
NumRows
orNumColumns
.Deleting Rows and Columns
Use the
deleteRows()
anddeleteColumns()
methods to remove rows and columns from the data source. When you delete a column, remaining cell values shift to the left; when you delete a row, existing cell values shift up.The
int num_rows)deleteRows()
anddeleteColumns()
methods are identical:
int num_columns)
- The position parameter specifies the first row or column number to delete from the data source.
- The num_rows or num_columns parameter specifies the number of rows or columns to be deleted, starting from the row or column specified by position.
When calling
deleteRows()
anddeleteColumns()
, note the following:
- The starting row or column cannot be greater than the
NumRows
orNumColumns
properties.- Both the
deleteRows()
anddeleteColumns()
methods returnfalse
if any of the parameters are invalid.Moving Rows and Columns
To move a range of rows or columns in the data source, use the
int num_rows,moveRows()
andmoveColumns()
methods. ThemoveRows()
andmoveColumns()
methods take the following forms:
int destination)
int num_columns,
int destination)
- The source parameter specifies the first row or column to move.
- The num_rows and num_columns parameters specify the number of rows or columns to move.
- The destination parameter specifies the row number above which, or the column number to the left of which, to move the rows or columns.
When calling
moveRows()
andmoveColumns()
, note the following:
- The starting (source) row or column cannot be greater than the value of the
NumRows()
orNumColumns()
properties.- Both the
moveRows()
andmoveColumns()
methods returnfalse
if any of the parameters are invalid.
3.4.2 Working with Other Properties
Setting Cell Values
To set the cell values in the data source, use the
setCell()
orsetCells()
methods. ThesetCells()
method can be a matrix of Strings or a vector of vectors. To remove all values, callclearCells()
.Adding and Removing TableDataListeners
The
JCVectorDataSource
class contains methods for adding and removing listeners to the data source:addTableDataListener()
andremoveTableDataListener()
. These methods monitor the data source for changes. For more information, see Section 3.7, Dynamically Updating Data.
3.5 Loading Data from an XML Source
3.5.1 XML Primer
XML - eXtensible Markup Language - is a scaled-down version of SGML (Standard Generalized Markup Language), the standard for creating a document structure. XML was designed especially for Web documents, and allows designers to create customized tags ("extensible"), thereby enabling a flexible approach to create common information formats for sharing both the format and the data on the Internet, intranets, and so on.
XML is similar to HTML in that both contain markup tags to describe the contents of a page or file. But HTML describes the content of a Web page (mainly text and graphic images) only in terms of how it is to be displayed and interacted with. XML, however, describes the content in terms of what data is being described. This means that an XML file can be used in various ways. For instance, an XML file can be utilized as a convenient way to exchange data across heterogeneous systems. As another example, an XML file can be processed (for example, via XSLT [Extensible Stylesheet Language Transformations]) in order to be visually displayed to the user by transforming it into HTML.
Here are links to more information on XML.
- http://www.w3.org/XML/ - another W3C site; contains exhaustive information on standards. Of particular note are the XML schema 1 (structures) and XML schema 2 (datatypes) working drafts. They make up an extension that specifies how to constrain XML documents to particular schema. This is important if you want to represent database data or object-oriented data as XML.
- http://www.javasoft.com/xml/tutorial_intro.html - Sun's XML site
- http://www.oasis-open.org/cover/xml.html - thorough list of links to XML papers and ongoing work
3.5.2 Using XML in JClass
In order to work with XML in your programs, or even to compile our XML examples, you will need to have the JAR files jaxp.jar and crimson.jar1 in your CLASSPATH. These files are distributed with JClass LiveTable - you can find them in JCLASS_HOME/lib/.
JClass LiveTable can accept XML data formatted to the specifications outlined in
com.klg.
jclass.util.xml.JCTableXMLParser
. This class takes in a stream of data and parses it under the assumption that it is in the defined XML format that JClass LiveTable uses. It then populates the specified table with the resulting data.Examples of XML in JClass
For XML data source examples, see the XMLFileData and XMLTableModelData examples in JCLASS_HOME/examples/table/datasource. These both use the colors.xml file in JCLASS_HOME/examples/table/datasource/.
You can also specify your own data parsing format. There are now constructors in the
JCInputStreamDataSource
,JCFileDataSource
,JCURLDataSource
, andJCAppletDataSource
classes that take an object that implements thecom.klg.
jclass.table.data.JCFileFormatParser
interface.Interpreter
The interpreter, which lets JClass LiveTable interpret the incoming data via the defined XML format, must be explicitly set by the user. The interpreter to use for JClass LiveTable is
com.klg.
jclass.table.data.JCXMLFormatParser
.Many constructors in the various data sources in JClass LiveTable take the
JCFileFormatParser
interface that this class (JCXMLFormatParser
) implements.Here are a few code examples that load XML data using this interpreter:
TableDataModel tdm = new JCFileDataSource(fileName,
new JCXMLFormatParser());
TableDataModel tdm = new JCURLDataSource(codeBase, fileName,
new JCXMLFormatParser());Note: A user can create a custom data format and create a custom data interpreter by implementing
JCFileFormatParser
.
3.5.3 Example XML Files for JClass LiveTable
Here is an XML file that contains data formatted to the specifications detailed in
<?xml version="1.0"?>com.klg.
jclass.util.xml.JCTableXMLParser
:
<!DOCTYPE JCTableData SYSTEM "JCTableData.dtd">
<JCTableData>
<Row>
<Cell>1</Cell> <Cell>2</Cell> <Cell>3</Cell> <Cell>4</Cell>
</Row>
<Row>
<Cell>1</Cell> <Cell>2</Cell> <Cell>3</Cell> <Cell>4</Cell>
</Row>
</JCTableData>Here is another example XML file that contains data formatted to the specifications detailed in
<?xml version="1.0"?>com.klg.
jclass.util.xml.JCTableXMLParser
, this one with row and column labels:
<!DOCTYPE JCTableData SYSTEM "JCTableData.dtd">
<JCTableData>
<ColumnLabel>Column 1</ColumnLabel>
<ColumnLabel>Column 2</ColumnLabel>
<ColumnLabel>Column 3</ColumnLabel>
<ColumnLabel>Column 4</ColumnLabel>
<Row>
<RowLabel>Row 1</RowLabel>
<Cell>1</Cell> <Cell>2</Cell> <Cell>3</Cell> <Cell>4</Cell>
</Row>
<Row>
<RowLabel>Row 2</RowLabel>
<Cell>1</Cell> <Cell>4</Cell> <Cell>9</Cell> <Cell>16</Cell>
</Row>
<Row>
<RowLabel>Row 3</RowLabel>
<Cell>1</Cell> <Cell>16</Cell> <Cell>81</Cell> <Cell>256</Cell>
</Row>
</JCTableData>
3.5.4 Tags
<ColumnLabel>
and<RowLabel>
tags are optional. Every<Row>
tag can contain any number of<Cell>
tags. These<Cell>
tags define the value of one cell within the row.
3.5.5 Creating a Swing TableModel class
For details on how to use the above XML format to create a Swing
TableModel
class instead of a standard JClass LiveTable data source, please look at thecom.klg.
jclass.util.xml.JCXMLTableModel
class. The user can pass an XML input stream to this object and use the resulting table model to populate a JClass LiveTable, a Swing JTable, a JClass Chart, or any other object that takes a SwingTableModel
class.Also, the XMLTableModelData example in JCLASS_HOME/examples/table/datasource shows this.
3.6 Creating your own Data Sources
If the stock data sources provided with JClass LiveTable do not meet your needs, you can easily create your own data source objects by implementing the
import com.klg.jclass.table.TableDataModel;TableDataModel
interface, as in the following example from examples/table/datasource/StaticDataSource.java:
import com.klg.jclass.table.JCTableDataListener;
public class StaticDataSource implements TableDataModel {
protected String data[];
public StaticDataSource(String strings[]) {
if(strings == null)
data = new String[0];
else
data = strings;
}
public Object getTableDataItem(int row, int column) {
if(column == 0)
return data[row];
else
return null;
}
public int getNumRows() {
return data.length;
}
public int getNumColumns() {
return 1;
}
public Object getTableRowLabel(int row) {
return Integer.toString(row);
}
public Object getTableColumnLabel(int column) {
return "Some Data";
}
public void addTableDataListener(JCTableDataListener l) {
}
public void removeTableDataListener(JCTableDataListener l) {
}
}The
StaticDataSource
class takes a one-dimensional array of Strings and turns it into a read-only data source. The constructors take the array of Strings; thegetTableDataItem()
method supplies the data as it is needed. Note that theaddTableDataListener()
andremoveTableDataListener()
methods have been left empty because this data source is not going to be changing dynamically, and thus does not need to keep track of its listeners. You can attach this data source to a table quite easily. To see a demonstration of this, run the StaticTest.java file, found in the examples/table/datasource directory.To make the items in the table editable, you must implement the
import com.klg.jclass.table.EditableTableDataModel;EditableTableDataModel
interface, as in examples/table/datasource/StaticEditableDataSource.java:
import com.klg.jclass.table.JCTableDataListener;
public class StaticEditableDataSource implements EditableTableDataModel {
protected String data[];
public StaticEditableDataSource(String strings[]) {
if(strings == null)
data = new String[0];
else
data = strings;
}
public Object getTableDataItem(int row, int column) {
if(column == 0)
return data[row];
else
return null;
}
public boolean setTableDataItem(Object o, int row, int column) {
if(column == 0) {
if (o instanceof String)
data[row] = (String)o;
else
data[row] = o.toString();
}
return true;
}
public int getNumRows() {
return data.length;
}
public int getNumColumns() {
return 1;
}
public Object getTableRowLabel(int row) {
return Integer.toString(row);
}
public Object getTableColumnLabel(int column) {
return "Some Data";
}
public void addTableDataListener(JCTableDataListener l) {
}
public void removeTableDataListener(JCTableDataListener l) {
}
}The
StaticEditableDataSource
class could have been a subclass ofStaticDataSource
, adding only thesetTableDataItem()
method, but in this example it was shown as a standalone class to make sure everything is as clear as possible. Note that the object that is passed back to the data source insetTableDataItem()
is not aString
.To see a demonstration of the
StaticEditableDataSource
class, run the StaticEditableTest.java file, found in the examples/table/datasource directory.
3.7 Dynamically Updating Data
Sometimes the data in the data source changes all by itself - for example, you may have a table displaying stock prices with data arriving in real-time over a network socket. As new prices arrive, your users would like the table to update the values of the appropriate cells.
To notify the table that the data has changed, send a
JCTableDataEvent
to all of theJCTableDataListener
objects that have registered themselves with the data source.The following is a simple example that creates a background thread that automatically updates cell values. It can be found in the file examples/table/datasource/DynamicDataSource.java:
import java.util.Enumeration;
import java.util.Random;
import com.klg.jclass.table.TableDataModel;
import com.klg.jclass.table.JCTableDataEvent;
import com.klg.jclass.table.JCTableDataListener;
import com.klg.jclass.util.JCListenerList;
public class DynamicDataSource implements TableDataModel, Runnable {
protected int data[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9,
};
protected JCListenerList listeners;
protected Thread kicker;
public DynamicDataSource() {
kicker = new Thread(this);
kicker.start();
}
public Object getTableDataItem(int row, int column) {
if (column == 0) {
return new Integer(data[row]);
}
return null;
}
public int getNumRows() {
return data.length;
}
public int getNumColumns() {
return 1;
}
public Object getTableRowLabel(int row) {
return Integer.toString(row);
}
public Object getTableColumnLabel(int column) {
return "Some Data";
}
public void addTableDataListener(JCTableDataListener l) {
listeners = JCListenerList.add(listeners,l);
}
public void removeTableDataListener(JCTableDataListener l) {
listeners = JCListenerList.remove(listeners,l);
}
public void run() {
Random random = new Random();
Enumeration e;
JCTableDataListener l;
JCTableDataEvent event;
int i;
for(;;) {
i = random.nextInt() % data.length;
if (i < 0) {
i = -i;
}
data[i] += (int)(random.nextGaussian()*10);
event = new JCTableDataEvent(this,i,0,0,0,
JCTableDataEvent.CHANGE_VALUE);
for(e = JCListenerList.elements(listeners); e.hasMoreElements(); ) {
l = (JCTableDataListener)e.nextElement();
l.dataChanged(event);
}
try {
Thread.sleep(100);
}
catch(Exception ex) {
}
}
}
}The
DynamicDataSource
class sendsCHANGE_VALUE
messages to all of its listeners whenever a value changes. When theJCTable
object receives this message it retrieves the new value from the data source and repaints the appropriate cell. There are several other update commands available on theJCTableDataEvent
class:
CHANGE_VALUE
NUM_ROWS
CHANGE_ROW
NUM_COLUMNS
CHANGE_COLUMN
ADD_COLUMN
CHANGE_ROW_LABEL
REMOVE_COLUMN
CHANGE_COLUMN_LABEL
MOVE_ROW
ADD_ROW
MOVE_COLUMN
REMOVE_ROW
RESET
All of the
CHANGE_
messages cause the Table to reload the specified data and repaint the intersection of the data that has been changed and the data that is being shown on screen.The file examples/table/datasource/DynamicTest.java demonstrates the simple technique used in DynamicDataSource.java.
Easy Listener Management
If you do not want to have to manage the listeners, JClass LiveTable includes a class called
AbstractDataSource
.AbstractDataSource
is an object provided byJCTable
that implementsTableDataModel
, and has methods for adding and removingJCTableDataListeners
. In addition, it contains several convenience methods for firing events, such asfireValueChanged()
andfireRowLabelChanged()
method.As an example, the DynamicDataSource.java program could be implemented again to use the
import java.util.Enumeration;AbstractDataSource
as follows:
import java.util.Random;
import com.klg.jclass.table.data.AbstractDataSource;
import com.klg.jclass.table.JCTableDataEvent;
import com.klg.jclass.table.JCTableDataListener;
import com.klg.jclass.util.JCListenerList;
public class DynamicDataSource2 extends AbstractDataSource
implements Runnable {
protected int data[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9,
};
protected Thread kicker;
public DynamicDataSource2() {
kicker = new Thread(this);
kicker.start();
}
public Object getTableDataItem(int row, int column) {
if(column == 0)
return new Integer(data[row]);
else
return null;
}
public int getNumRows() {
return data.length;
}
public int getNumColumns() {
return 1;
}
public Object getTableRowLabel(int row) {
return Integer.toString(row);
}
public Object getTableColumnLabel(int column) {
return "Some Data";
}
public void run() {
Random random = new Random();
Enumeration e;
JCTableDataListener l;
JCTableDataEvent event;
int i;
for(;;) {
i = random.nextInt() % data.length;
if (i < 0) {
i = -i;
}
data[i] += (int)(random.nextGaussian()*10);
event = new JCTableDataEvent(this,i,0,0,0,
JCTableDataEvent.CHANGE_VALUE);
fireTableDataEvent(event);
try {
Thread.sleep(100);
}
catch(Exception ex) {
}
}
}
}Running examples/table/datasource/DynamicTest2.java demonstrates that the same results can be achieved more easily by using a subclass of
AbstractDataSource
.
3.7.1 Adding and Removing Columns and Rows
ADD_ROW
,REMOVE_ROW
,ADD_COLUMN
, andREMOVE_COLUMN
notify the table that a row or column has been added or removed so that the table can update its internal list of cell attributes. For example, if all your rows are different colors, and you delete a row, the remaining rows will still have the correct colors if you send aREMOVE_ROW
message to theJCTable
. Some of the event parameters may be ignored for row or column operations. For example, when you do an operation on an entire row or column, if you create anADD_ROW
event, the column parameter is ignored by the table. With the exception of theMOVE_
events, all of the events ignore the num_affected and destination parameters of theJCTableDataEvent
.The
MOVE_ROW
andMOVE_COLUMN
commands are the only commands that make use of the num_affected and destination parameters in theJCTableDataEvent
. When you have aMOVE_
event, you can move multiple rows/columns (the num_affected parameter) and you must specify to which row/column you are moving (destination).The
RESET
message causes theJCTable
object to re-initialize itself by re-reading the number of rows, number of columns and all the data from the data source. The table's visual attributes, such as fonts and colors, are not affected.Note: When a user edits a cell in the table and the value is put back into the data source via
setTableDataItem()
, the table will automatically repaint the cell with a new value.1You may substitute for crimson.jar any parser that is compliant with Sun's JAXP 1.1 specification. See Sun's JAXP documentation for more information: