我对Swing很新,并尝试使用JTable写一个属性表,但我看到了一些奇怪的行为。我预留了NetBeans并编写了这个小宝石,看看基础是否有效。如果您想知道,我的真正的应用程序是JTextField的子类,并提供对话框以帮助用户指定一些值; ImportField就是其中一个类。
此程序显示JTable但它只有列标题。 JTable从不调用getValueAt,因此不会显示任何数据。
任何人都可以帮我理解这种行为吗?
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));
}
}
非常感谢您的帮助。
答案 0 :(得分:1)
尝试此操作后,在设置模型后,请调用:
((DefaultTableModel)table.getModel()).fireTableDataChanged();
答案 1 :(得分:0)
我发现你需要调用table.validate();
(当然,在设置TableModel之后)
答案 2 :(得分:0)
问题来自于你扩展了DefaultTableModel而你没有实现方法:
public int getRowCount()
以下是初始化模型时的步骤 与
final Model model = new Model();
[有关这些步骤的详细解释,请阅读此帖Are fields initialized before constructor code is run in Java?]
现在,由于你没有覆盖getRowCount(),Model类将使用超类DefaultTableModel中的实现,它将一直返回0,因此表总是会#34;思考&#34;没有什么可以展示的。