JTable没有调用getValueAt

时间:2015-05-12 17:37:06

标签: jtable

我对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));
    }
}

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

尝试此操作后,在设置模型后,请调用:

((DefaultTableModel)table.getModel()).fireTableDataChanged();

答案 1 :(得分:0)

我发现你需要调用table.validate();(当然,在设置TableModel之后)

答案 2 :(得分:0)

问题来自于你扩展了DefaultTableModel而你没有实现方法:

public int getRowCount()

以下是初始化模型时的步骤 与

final Model model = new Model();
  1. 调用超类(DefaultTableModel)构造函数(但它的基础数据为空)。
  2. 模型的私有字段已初始化(colNames和数据)
  3. 执行Model&#39的构造函数的其余部分
  4. [有关这些步骤的详细解释,请阅读此帖Are fields initialized before constructor code is run in Java?]

    现在,由于你没有覆盖getRowCount(),Model类将使用超类DefaultTableModel中的实现,它将一直返回0,因此表总是会#34;思考&#34;没有什么可以展示的。