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