Multiple Tables with Common Cell Values · Performance Improvement
Using an External Data File · Live Data Updating
This chapter covers topics that programmers of advanced JClass LiveTable Pro applications will find useful. It assumes that you are already familiar with JClass LiveTable Pro.
Components in cells/labels are useful for providing menus or buttons within a table.
Components can be located individually in cells, or a class of components can be placed in an entire row or column. In the latter case, sufficient components are created only as necessary as the table is scrolled.
The following example uses setComponent() to place a component in a series of cells. Buttons are put in every cell in the first column, and the labels are put in every cell in the third column.
table.setComponent(JCTblEnum.ALLCELLS, 0, new Button()); table.setComponent(JCTblEnum.ALLCELLS, 2, new Label());
JCCellPosition pos = table.getPosition(myComponent, null); button.setLabel(table.getCell(pos.row, pos.column).toString());
A JCCreateComponentListener can change the component member. This allows new items to be created as needed, as demonstrated by the creation and display of a Button in the following code fragment:
public void createComponent(JCCreateComponentEvent ev) { if (ev.getColumn() == 0) ev.setComponent(new Button()); else if (ev.getColumn() == 2) ev.setComponent(new Label()); } public void displayComponent(JCDisplayComponentEvent ev) { if (ev.getColumn() == 0) { Button button = (Button)ev.getComponent(); }
To register a JCDisplayComponentListener, use addDisplayComponentListener() , as shown in the following line of code:
table.addDisplayComponentListener(this);
<APPLET> ... <PARAM NAME=componentList value="(allcells 4 Button)"> ... </APPLET>
To specify a third-party component in an HTML file, use its full class name as in the following HTML file fragment:
<APPLET> ... <PARAM NAME=componentList value="(1 1 jclass.table.JCTable)"> ... </APPLET>
Property Value | Data Type |
---|---|
JCTblEnum.TYPE_STRING |
Any text string |
JCTblEnum.TYPE_DOUBLE |
Double-precision value |
JCTblEnum.TYPE_INTEGER |
Integer value |
JCTblEnum.TYPE_FLOAT |
Floating-point value |
JCTblEnum.TYPE_BOOLEAN |
Any Boolean value |
table.setValidatePolicy(JCTblEnum.VALIDATE_USER_EDIT); table.addValidateCellListener(this);
Numeric validation (through the DataType and ValidationPolicy properties) is performed using Java routines like Double.valueOf(string).doubleValue(). These routines can be problematic, allowing trailing non-numeric characters. If this is a concern, add a JCValidateCellListener to validate the data.
The two listener methods are validateCellBegin or validateCellEnd. The getChanged() method is used to indicate whether the user has attempted to change the cell. The Value property can be modified to point to a new value for the cell. The setAllowValueChange() method can be set to false to reject the data. The following example validates both integer and floating-point data using two different techniques:
public void validateCellBegin(JCValidateCellEvent ev) {} public void validateCellEnd(JCValidateCellEvent ev) { if (ev.getColumn() == 1) { Integer in = (Integer)ev.getValue(); if (in.intValue() > 60) { System.out.println("Integer too large"); ev.setAllowValueChange(false); } } else if (ev.getColumn() == 2) { Double db = (Double)ev.getValue(); if (db.doubleValue() > 60.0) { System.out.println("Double too large - set to 60.0"); ev.setValue(new Double(60.0)); } } }
To accomplish this, set the values in one table, get the Cells Vector from it using getCells(), and then set the values in the other table using setCells().
If users should be able to edit the cells in any of the tables, you should use ValidateCell to capture cell editing and update both the corresponding cell value in the other table.
All of this is shown by the following example:
import jclass.table.JCTable; import jclass.table.JCTblEnum; import jclass.table.JCValidateCellEvent; import jclass.table.JCValidateCellListener; import jclass.util.JCVector; import java.awt.*; import java.applet.Applet; public class s6c extends Applet implements JCValidateCellListener { JCTable table1; JCTable table2; String cells[][] = { {"James Q. Doohan","1701 Planetia Blvd.\nAnytown, U.S.A.", "","President","$245,000"}, {"John F. Kricfalusi","983 Nickelodeon Street\nAnytown, U.S.A.", "(999) 555-9876","Animator","$1,000"}, {"Marc Lenard","6 Gene Crescent\nAnytown, U.S.A.", "(999) 555-1212","Telemarketer","$10 / hr."}, {"Hikaru I. Takei","134 Adelaide Street E.\nSuite 204\nAnytown, U.S.A." ,"(999) 594-1026","OEM Sales","50%"}, {"Melissa A. Truman","475 Woodview Line\nAnytown, U.S.A.", "(999) 555-9030","Technical Writer","$5,250"}, {"Stephanie L. Truman","388 Appleby Road\nAnytown, U.S.A.", "(999) 555-2642","System Analyst","$85,750"}, {"Bill West Jr","1001 Spumco Way\nAnytown, U.S.A.", "(999) 555-9966","Announcer","$17,500"}, {"Stephen L. Truman","388 Appleby Road\nAnytown, U.S.A.", "(999) 555-2642","Motivational Speaker","$250,000"}, {"Bill West","1001 Spumco Way\nAnytown, U.S.A.", "(999) 555-9966","Father Figure","$7,500"} }; public void init() { setLayout(new GridLayout(2,1)); table1 = new JCTable(); table2 = new JCTable(); add(table1); add(table2); table1.setNumRows(9); table1.setNumColumns(5); table2.setNumRows(9); table2.setNumColumns(5); JCVector cellsV = new JCVector(cells.length); for (int i = 0; i < cells.length; i++) cellsV.setElementAt(i, new JCVector(cells[i])); table1.setCells(cellsV); table2.setCells(cellsV); table1.setValidatePolicy(JCTblEnum.VALIDATE_USER_EDIT); table2.setValidatePolicy(JCTblEnum.VALIDATE_USER_EDIT); table1.addValidateCellListener(this); table2.addValidateCellListener(this); } public void validateCellBegin(JCValidateCellEvent ev) {} public void validateCellEnd(JCValidateCellEvent ev) { if (ev.getSource() == table1) table2.paint(ev.getRow(), ev.getColumn()); else table1.paint(ev.getRow(), ev.getColumn()); } }
The stocks demo demonstrates many of these methods for many JClass LiveTable Pro tasks (including adding rows, columns and values).
For example, if the background color for most of your table cells is blue, with a few that are red or green, set the default background context to blue first:
table.setBackground(JCTblEnum.ALL, JCTblEnum.ALL, Color.blue);Then, define individual contexts for your red and green cells.
In some cases it is more desirable to load the data from an external source containing no HTML elements or tags. One advantage is that the data can easily be altered without having to know HTML, and that changes made to this file cannot adversely affect the way information is laid out on a Web page either through accident or omission.
Using this method, you can manipulate cell values but not any table properties.
The following code listing is for a program that loads the cell values from an external data file.
1. import jclass.table.JCTable; 2. import jclass.table.JCTblEnum; 3. import jclass.util.JCVector; 4. import jclass.util.JCFile; 5. import java.awt.*; 6. import java.applet.Applet; 7. public class table6 extends Applet { 8. static String file = "table6.dat"; 9. public void init() { 10. setLayout(new GridLayout(1,1)); 11. // Create table 12. JCTable table = new JCTable(); 13. // Set table size in terms of rows and columns 14. table.setNumRows(7); 15. table.setNumColumns(5); 16. // Read values for cells from file 17. JCVector cells = JCFile.read(this, file, ',', true); 18. // Set values for cells 19. table.setCells(cells); 20. // Set cell colors 21. table.setBackground(JCTblEnum.ALL, JCTblEnum.ALL, Color.yellow); 22. table.setForeground(JCTblEnum.ALL, JCTblEnum.ALL, Color.blue); 23. // Set cell sizes 24. table.setPixelWidth(JCTblEnum.ALL, JCTblEnum.VARIABLE); 25. table.setPixelHeight(JCTblEnum.ALL, JCTblEnum.VARIABLE); 26. add(table); 27. } 28. }
As you can see from the source code, table6.java shares much of the code with table1.java (see Figure 1), but whereas table1.java contains its cell values within the program, table6.java retrieves its cell values from table6.dat.
Line 8 specifies the location (URL) of the data file containing the table data. 1 Line 17 specifies the characters that are used as delimiters within the data file. Lines 17 contains the code that retrieves the values of the table's cells from the URL using JCFile.read.
The following code listing displays the HTML code for table6.dat, whose values are loaded into the cells in table6.java.
James Q. Doohan,1701 Planetia Blvd. Anytown U.S.A.,,President,$245,000 John F. Kricfalusi,983 Nickelodeon Street Anytown U.S.A.,(999) 555-9876,Animator,$1,000 Marc Lenard,6 Gene Crescent Anytown U.S.A.,(999) 555-1212,Telemarketer,$10 / hr. Hikaru I. Takei,134 Adelaide Street E. Suite 204 Anytown U.S.A.,(999)594-1026,OEM Sales,50% Melissa A. Truman,475 Woodview Line Anytown U.S.A.,(999) 555-9030,Technical Writer,$5,250 Stephanie L. Truman,388 Appleby Road Anytown U.S.A.,(999) 555-2642,System Analyst,$85,750 Bill West,1001 Spumco Way Anytown U.S.A.,(999) 555-9966,Announcer,$17,500 |
There are advantages and disadvantages to using this method to load data. One advantage is the cell data can easily be changed using a simple editing program, whereas table1.java would have to be edited and recompiled to reflect any changes. A disadvantage of using this method is the act of retrieving the data from another file makes table6.java run more slowly than table1.java.
// Set data types for the columns table.setDatatype(JCTblEnum.ALLCELLS, 1, JCTblEnum.TYPE_DOUBLE); table.setDatatype(JCTblEnum.ALLCELLS, 2, JCTblEnum.TYPE_DOUBLE); table.setDatatype(JCTblEnum.ALLCELLS, 3, JCTblEnum.TYPE_DOUBLE); table.setDatatype(JCTblEnum.ALLCELLS, 4, JCTblEnum.TYPE_INTEGER); // Read the data from the file. Data is comma-separated. JCVector values = JCFile.read(this, "american.dat", ',', false); // Convert the data to the data types in the table table.convert(values, 0, 0); // Add the data to the table. table.setCells(values); // Set the number of rows in the table. table.setNumRows(values.size());
This code is used within the javaexpo demonstration files, which derives its "live" cell values from an external data file.
While there are no socket data retrieval routines included in JClass LiveTable Pro, it is possible to use a JCCellValueListener to allow an application to retrieve data in a cell-by-cell basis.
1 You may have to alter the source code in table6.java to point to the directory containing table2.dat on your system.