I'm pretty new to Swing and trying to write a property sheet using JTable but am seeing some strange behavior. I set aside NetBeans and coded this little gem to see if the basics worked. In case you are wondering, my real app subclasses JTextField and puts up dialog boxes to help the user specify some of the values; ImportField is one of those classes.
This program displays the JTable but it only has the column headings. JTable never invokes getValueAt so no data is displayed.
Can anyone help me understand this behavior?
import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.TableModelEvent;
public class Y extends JFrame {
public Y() {
super("Y");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final Model model = new Model();
JTable table = new JTable();
table.setModel(model);
JScrollPane scrollpane = new JScrollPane(table);
JButton button = new JButton("Click Me");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
model.setValueAt(model.getValueAt(0, 1), 0, 1);
}
});
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollpane, BorderLayout.CENTER);
panel.add(button, BorderLayout.SOUTH);
setContentPane(panel);
pack();
}
public static void main (String[] args) throws Exception {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Y().setVisible(true);
}
});
}
}
class ImportField extends JTextField implements FocusListener {
public ImportField() {
super();
this.setInputVerifier(new ImportVerifier());
this.addFocusListener(this);
this.setBorder(null);
}
@Override
public void focusGained(FocusEvent e) {
// We only want to do this ONCE
this.removeFocusListener(this);
System.out.println("Text field gained focus.");
}
@Override
public void focusLost(FocusEvent e) {
// IGNORE
}
class ImportVerifier extends InputVerifier {
@Override
public boolean verify(JComponent input) {
boolean valid = true;
JTextField fld = (JTextField) input;
if (fld.getText().length() > 0) {
StringTokenizer tok = new StringTokenizer(fld.getText(), ", ");
while (tok.hasMoreTokens()) {
String token = tok.nextToken().toLowerCase();
if ( ! token.equals("insert") && ! token.equals("update") &&
! token.equals("ignore") && ! token.equals("abort") &&
! token.equals("none") && ! token.equals("all")) {
valid = false;
}
}
}
return valid;
}
}
}
class Model extends DefaultTableModel {
private String[] colNames = { "Key", "Value" };
private Object[][] data = { { "item 1", "something" },
{ "item 2", "something else" },
{ "item 3", "other thing" } };
@Override
public Class<?> getColumnClass(int columnIndex) {
System.out.format("%-15s %s\n", "getColumnClass", "String");
return String.class;
}
@Override
public int getColumnCount() {
System.out.format("%-15s %d\n", "getColumnCount", colNames.length);
return colNames.length;
}
@Override
public String getColumnName(int columnIndex) {
System.out.format("%-15s %s\n", "getColumnName", colNames[columnIndex]);
return colNames[columnIndex];
}
public int geRowlumnCount() {
System.out.format("%-15s %d\n", "getRowName", data.length);
return data.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
System.out.format("%-15s %s\n", "getValueAt", data[rowIndex][columnIndex]);
return data[rowIndex][columnIndex];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
System.out.format("%-15s %s\n", "isCellEditable", rowIndex == 1);
return rowIndex == 1;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
System.out.format("%-15s %s\n", "setValueAt", aValue);
data[rowIndex][columnIndex] = aValue;
fireTableChanged(new TableModelEvent(this));
}
}
Your help will be much appreciated.