Name: tb29552 Date: 10/02/98
/*
In Swing 1.02 JTable:
- Header height is zero until setVisble(true)
- Header height + (rowCount * rowHeight) does
not give correct preferred height
- Pixel fudge factor must be added to preferred
width to get correct appearance in scroller
A test class duplicating these bugs follows.
Sorry it's not very concise, since it was my
main JTable test class.
package org.jcon.test;
*/
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.table.*;
/**
* Test JTable for technique required to size columns,
* provide data, make splitter work, etc.
* java TestJTable
*
* @author Jack Harich
*/
public class TestJTable implements ActionListener, MouseListener {
//---------- Private Fields ------------------------------
private Frame frame = new Frame("Test JTable");
private EntityModel entityModel = new EntityModel();
private JTable entityTable = new JTable(entityModel);
private int entityRowCount = 3;
private String entityData = "Data";
private StructureModel structureModel = new StructureModel();
private JTable structureTable = new JTable(structureModel);
// false for Windows mostly, true for metal
private static boolean useCrossPlatformLookAndFeel = false;
//---------- Initialization ------------------------------
public TestJTable () {
print(" - Please wait....");
installLookAndFeel();
frame.setBackground(Color.lightGray);
//----- Configure panes
// Entity pane
// JScrollPane entityScrollPane =
// JTable.createScrollPaneForTable(entityTable);
JScrollPane entityScrollPane = new JScrollPane(entityTable);
entityScrollPane.setMinimumSize(new Dimension(0, 0));
// Structure pane
// *** createScrollPaneForTable() DEPRECATED ***
// JScrollPane structureScrollPane =
// JTable.createScrollPaneForTable(structureTable);
JScrollPane structureScrollPane = new JScrollPane(structureTable);
structureScrollPane.setMinimumSize(new Dimension(0, 0));
// Put panes in splitter
JSplitPane splitPane = new JSplitPane(JSplitPane.
HORIZONTAL_SPLIT, entityScrollPane, structureScrollPane);
// splitPane.setDividerLocation(200); // NO EFFECT ***
splitPane.setContinuousLayout(false); // Until buffer
splitPane.setDoubleBuffered(true);
frame.add("Center", splitPane);
//----- Configure other
Panel buttonBar = new Panel();
buttonBar.add(createButton("Reload Entity Data", "Reload"));
buttonBar.add(createButton("Select 2", "Select2"));
buttonBar.add(createButton("Select 3", "Select3"));
frame.add("South", buttonBar);
//----- Configure tables
// entityTable
entityTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
addColumn(entityTable, 0, 15, "Entity Name");
addColumn(entityTable, 1, 18, "Status");
// structureTable
structureTable.addMouseListener(this);
structureTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
addColumn(structureTable, 0, 15, "Column");
addColumn(structureTable, 1, 10, "Type");
addColumn(structureTable, 2, 25, "Properties");
//frame.setVisible(true);
// Now that columns are defined setPreferredSize()
// extra for Swing bug.
// Metal - use 3, 2 will cause horizontal scroller to appear
// Windows - use 5.
int prefWidth = entityTable.getPreferredSize().width;
int prefHeight = calcPreferredTableHeight(6);
entityScrollPane.setPreferredSize(new Dimension(
prefWidth + 5, prefHeight));
prefWidth = structureTable.getPreferredSize().width;
structureScrollPane.setPreferredSize(new Dimension(
prefWidth + 7, prefHeight)); // 5 not enough
frame.pack(); // Works since preferredSize set
frame.setVisible(true);
}
private int calcPreferredTableHeight(int rowCount) { // Was 400
Dimension headerSize = entityTable.getTableHeader().getSize();
print(" - Preferred header height = " + headerSize.height);
print(" - Row height = " + entityTable.getRowHeight());
int height = headerSize.height +
(rowCount * (entityTable.getRowHeight()));
print(" - Calculated preferred height for " + rowCount + " rows = " + height);
return height;
}
private Button createButton(String text, String command) {
Button button = new Button(text);
button.setActionCommand(command);
button.addActionListener(this);
return button;
}
public static void main(String args[]) {
new TestJTable ();
}
//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
String command = evt.getActionCommand().intern();
if (command == "Reload") {
entityRowCount = entityRowCount + 2;
entityData += "X";
entityModel.fireTableDataChanged();
} else if (command == "Select2") {
// structureTable.getSelectionModel()
// .setAnchorSelectionIndex(2);
structureTable.setEditingRow(2);
} else if (command == "Select3") {
structureTable.getSelectionModel()
.setLeadSelectionIndex(3);
}
}
//---------- MouseListener Implementation ----------------
public void mouseClicked(MouseEvent evt) {
if (evt.getSource() == structureTable) {
int index = getSelectedIndex();
print(".mouseClicked() - index = " + index);
if (index < 0)
return; // Clicked off grid
if (evt.getClickCount() == 1) {
print(".mouseClicked() single " + index);
} else if (evt.getClickCount() == 2) {
print(".mouseClicked() double " + index);
}
}
}
public void mousePressed(MouseEvent evt) {
}
public void mouseReleased(MouseEvent evt) {
}
public void mouseEntered(MouseEvent evt) {
}
public void mouseExited(MouseEvent evt) {
}
// Returns -1 if none
public int getSelectedIndex() {
int index = structureTable.getSelectedRow();
// Swing bug, index can be > items.size() - 1
if (index < 0 || index > 10) {
return -1; // Clicked on whitespace
} else {
return index;
}
}
//---------- Public Methods ------------------------------
/**
* Installs the LookAndFeel as defined by the current
* constant. Call this once in system startup. (from WindowLib)
*/
public static void installLookAndFeel() {
try {
// Could use UIManager.setLookAndFeel(
// "com.sun.java.swing.plaf.metal.MetalLookAndFeel");
if (useCrossPlatformLookAndFeel) {
UIManager.setLookAndFeel(UIManager
.getCrossPlatformLookAndFeelClassName());
} else {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
}
} catch(Exception ex) {
print(".installLookAndFeel() - Cannot set look and feel");
ex.printStackTrace();
}
}
//---------- Private Methods -----------------------------
private void addColumn(JTable table, int index,
int columns, String label) {
int calcWidth = getColumnsWidth(columns, (Component) table);
TableColumn column = new TableColumn();
column.setModelIndex(index);
column.setHeaderValue(label);
column.setWidth(calcWidth);
table.addColumn(column);
}
/**
* Returns the number of pixels required for the number of
* columns to draw "average" text on the Component.
* Useful for setting TableColumn's width. (from VisualLib)
*/
// Note that the technique in JTextField.getColumnWidth()
// produces about 50% too wide a result
// This is return columns * metrics.charWidth('m');
private static int getColumnsWidth(int columns, Component comp) {
FontMetrics metrics = comp.getToolkit().getFontMetrics(
comp.getFont());
String text = "AbCdEfGhIjKlMnOpQrStUvWxYzAbCd"; // 30
int textWidth = metrics.stringWidth(text);
return (textWidth * columns) / 30;
}
//--- Std
private static void print(String text) {
System.out.println("TestJTable" + text);
}
//========== Inner Classes ===============================
class EntityModel extends AbstractTableModel {
//----- Abstract implementation -----
// ColumnCount = 0 since we supply TableColumns above
public int getColumnCount() {
return 0;
}
public int getRowCount() {
return entityRowCount;
}
public Object getValueAt(int row, int col) {
return entityData + (++row * ++col);
}
//----- Superclass Overrides -----
// Had to override since protected
protected void fireTableDataChanged() {
super.fireTableDataChanged();
}
} // End inner class
class StructureModel extends AbstractTableModel {
//----- Abstract implementation -----
// ColumnCount = 0 since we supply TableColumns above
public int getColumnCount() {
return 0;
}
public int getRowCount() {
return 10;
}
public Object getValueAt(int row, int col) {
switch (col) {
case 0:
return "UserID";
case 1:
return "String";
case 2:
return "Soft and cuddly";
default:
return "#Error#";
}
}
} // End inner class
} // End outer class
(Review ID: 34396)
======================================================================