2013-04-23 80 views
3

我发现更新数据的示例,但它使用DefaultTableModel。当我创建自己的TableModel和我自己的数据类时,当我将数据添加到JTable时,它不会更新。不更新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<Person> data = new LinkedList<Person>(); 
    private LinkedList<Person> data = new LinkedList<Person>(); 
    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<Person> data = new LinkedList<Person>(); 
    private LinkedList<Person> data = new LinkedList<Person>(); 
    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中进行正确的数据更新?

回答

4

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

  • 你覆盖了fireTableDataChanged(),给它一个空的方法体从而绕过了超级的方法中包含的所有魔法,使之基本上是毫无价值的方法,
  • 并且在更改模型数据后,您没有调用任何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接口类型,因此您可以根据需要更改集合对象的数据类型。

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

如果你这样说“不工作”,你不解释怎样和为什么它不工作,你可能是什么错误看,并没有显示出你的代码实现,你配合我们的手,阻止我们从能够有效地帮助你。如果您需要我们的帮助,请考虑向我们提供足够的信息,以便我们了解您的问题。这将包括向我们展示您的代码的任何更改,显示任何编译错误或异常消息,并详细描述您的问题的具体情况。

编辑3
在你最近的代码迭代,你的addElement方法做的一切,但添加元素

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

你不会在上面的方法中向LinkedList添加任何东西!

+1

指出AbstractTableModel已经为你实现了fireTableDataChanged,因此你鼓励不要重写它的原因是 – MadProgrammer 2013-04-23 20:45:37

+0

Thx,但是当我调用model.addElement(person);方法和之后model.fireTableDataChanged()它不能正常工作。 – veinhorn 2013-04-23 21:03:17

+0

@BorisMonson:模型本身应该调用fire方法,他们应该在他们的add,remove方法中执行此操作,例如在上面的小代码片段中。另外:为什么要添加“听众”?另外为什么使用LinkedList作为模型的集合? – 2013-04-23 21:04:19