不要更新JTable

我找到了更新数据的示例,但它使用了DefaultTableModel。 当我创建自己的TableModel和我自己的数据类时,当我将数据添加到JTable时它不会更新。

如何向TableModel添加监听器?

这是我的代码:

package by; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.util.LinkedList; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; public class DialogEg { private static void createAndShowGui() { MainWin mainPanel = new MainWin(); JFrame frame = new JFrame("DialogEg"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } class MainWin extends JPanel { private String[] COL_NAMES = { "Last Name", "First Name" }; //private DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0); private MyTableModel model = new MyTableModel(); private JTextField lastNameField = new JTextField(15); private JTextField firstNameField = new JTextField(15); public MainWin() { final JPanel dataPanel = new JPanel(); dataPanel.add(new JLabel("Last Name:")); dataPanel.add(lastNameField); dataPanel.add(Box.createHorizontalStrut(15)); dataPanel.add(new JLabel("First Name:")); dataPanel.add(firstNameField); JPanel btnPanel = new JPanel(); btnPanel.add(new JButton(new AbstractAction("Add Name") { @Override public void actionPerformed(ActionEvent arg0) { lastNameField.setText(""); firstNameField.setText(""); int result = JOptionPane.showConfirmDialog(MainWin.this, dataPanel, "Enter Name", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { String lastName = lastNameField.getText(); String firstName = firstNameField.getText(); Object[] dataRow = new String[] { lastName, firstName }; //model.addRow(dataRow); Person person = new Person(); person.setFirstName(firstName); person.setLastName(lastName); model.addElement(person); model.fireTableDataChanged(); } } })); setLayout(new BorderLayout()); JTable jtable = new JTable(model); //new JTable(model) jtable.setModel(model); add(new JScrollPane(jtable), BorderLayout.CENTER); add(btnPanel, BorderLayout.SOUTH); } } class MyTableModel extends AbstractTableModel { private String[] columnNames = { "Last name", "First name" }; //private LinkedList data = new LinkedList(); private LinkedList data = new LinkedList(); public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.size(); } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row,int col) { switch(col) { case 0: { return data.get(col).getLastName(); } case 1: { return data.get(col).getFirstName(); } default: return ""; } } public void addElement(Person person) { data.add(person); } public void fireTableDataChanged() { } } class Person { String last_name; String first_name; public Person() { } public void setLastName(String l_name) { last_name = l_name; } public void setFirstName(String f_name) { first_name = f_name; } public String getLastName() { return last_name; } public String getFirstName() { return first_name; } } 

EDIT2

这里我使用方法addElement:

  public void actionPerformed(ActionEvent arg0) { lastNameField.setText(""); firstNameField.setText(""); int result = JOptionPane.showConfirmDialog(MainWin.this, dataPanel, "Enter Name", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { String lastName = lastNameField.getText(); String firstName = firstNameField.getText(); Person person = new Person(); person.setFirstName(firstName); person.setLastName(lastName); //here i use add element model.addElement(person); } } 

有我的桌子型号:

 class MyTableModel extends AbstractTableModel { private String[] columnNames = { "Last name", "First name" }; //private LinkedList data = new LinkedList(); private LinkedList data = new LinkedList(); public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.size(); } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row,int col) { switch(col) { case 0: { return data.get(col).getLastName(); } case 1: { return data.get(col).getFirstName(); } default: return ""; } } public void addElement(Person person) { int firstRow = data.size() - 1; int lastRow = firstRow; fireTableRowsInserted(firstRow, lastRow); } } 

当我添加任何信息,但它没有更新。 我必须在jtable中将此方法用于正确的数据更新吗?

你做了两件非常危险的事情:

  • 你重写了fireTableDataChanged()并给它一个空方法体,从而绕过了super方法所包含的所有魔法,使它基本上成为一个毫无价值的方法,
  • 并且在更改模型的数据后,您不会调用任何fireXXXChanged()方法。

我建议你做相反的事情:

  • 不要覆盖fireTableDataChanged()
  • 更改数据时调用fireXXX()方法。

例如:

 public void addElement(Person person) { data.add(person); int firstRow = data.size() - 1; int lastRow = firstRow; fireTableRowsInserted(firstRow, lastRow); } // public void fireTableDataChanged() { // // } 

暂且不说:为什么要为JTable或其TableModel添加一个监听器?

编辑2
你说:

我以为我必须实现firexxx方法之一。

您的类扩展AbstractTableModel类而不是实现TableModel接口的原因是为了获得AbstractTableModel类必须提供的所有好东西,包括它的fireXXX(...)方法。 他们已经连线通知任何使用数据已更改的模型的JTable。 如果你覆盖它们,特别是如果你覆盖它们并且不调用任何超级方法,那么你已经破坏了这个有用的代码,它将不再起作用。

至于LinkedList,我想尝试使用另一个集合(没有像所有样本中的数组)。

由于您通常希望以随机方式访问数据,我认为您可以从ArrayList中获得更多收益。 无论如何,集合变量应该是List接口类型,因此您可以根据需要更改集合对象的数据类型。

我不明白为什么当我使用你的实现它不起作用。

如果你说某些“不起作用”并且你没有解释它是如何或为什么不起作用,你可能会看到什么错误,并且没有展示你的代码实现,你就会束手束脚,阻止我们帮助你有效。 如果您需要我们的帮助,请考虑向我们提供足够的信息,以便我们了解您的问题。 这将包括向我们显示代码的任何更改,显示任何编译错误或exception消息,并详细描述您的问题的具体细节。

编辑3
在最近的代码迭代中,addElement方法会执行除了添加元素之外的所有操作

 public void addElement(Person person) { int firstRow = data.size() - 1; int lastRow = firstRow; fireTableRowsInserted(firstRow, lastRow); } 

您不会在上面的方法中向LinkedList添加任何内容!