2013-04-16 42 views
4

在我的搖擺屏幕上有一個JTable。在加載屏幕時,我只設置一個爲此表創建的表模型。 在運行時如果有任何數據更改,我正在重新創建相同的模型,並再次使用objJTable.setModel(objCustTableModel)進行設置。JTable.setModel()的行爲

現在問題是在屏幕加載時加載的表模型,同時在運行時設置objJTable.setModel(objCustTableModel)時調用同一模型對象,從CustTableModel類調​​用getColumnClass(int col)方法。在這個對象調用之後,我的新模型對象被調用。再次如果我設置另一個新的 表模型,通過使用相同的代碼objJTable.setModel(objCustTableModel2),模型調用的功能首先從objCustTableModel調用,然後 objCustTableModel2

總之setModel()函數先調用先前的模型對象,然後調用當前的模型對象。我怎樣才能限制以前的模型對象的調用?

例如

import java.awt.Cursor; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.AbstractTableModel; 


/** 
* Steps to reproduce issue. 
* 1. Run this program. 
* 2. There will be two rows in table. Delete all rows one by one. 
* 3. Now click on Add button and see the exception. 
* 
* I come to know that this exception is because of table.setAutoCreateRowSorter(true); line, which is there in TestCustTableModel's constructor 
* If you comment this line, then issue got resolved. 
* But I want to apply sorting on columns so this line is required. 
*/ 

public class TestCustTableModel extends JPanel{ 
    JTable table = new JTable(); 
    public TestCustTableModel() { 

     Object[][] data = new Object[2][3]; 
     data[0][0] = "1"; 
     data[0][1] = "User1"; 
     data[0][2] = "Delete"; 

     data[1][0] = "2"; 
     data[1][1] = "User2"; 
     data[1][2] = "Delete"; 

     JButton addButton = new JButton("Add"); 
     addButton.addMouseListener(new AddListener()); 
     table.setModel(new CustModel(data)); 
     table.addMouseListener(new TableListener()); 

     /**################################# 
     * Following line throws ArrayIndexOutOfBoundsException. Please comment or Uncomment following line and see the difference. 
     */ 
     table.setAutoCreateRowSorter(true); 


     table.getTableHeader().setCursor(new Cursor(Cursor.HAND_CURSOR)); 
     JScrollPane scrollPane = new JScrollPane(table); 

     this.add(addButton); 
     this.add(scrollPane); 
    } 


    class TableListener extends MouseAdapter { 
     public void mouseClicked(MouseEvent evnt) { 
      Point p = evnt.getPoint(); 
      if(table.columnAtPoint(p) == 2) { 
       Object[][] data = null; 
       if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 0) { 
        data = new Object[1][3]; 
        data[0][0] = "2"; 
        data[0][1] = "User2"; 
        data[0][2] = "Delete"; 
       }else if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 1) { 
        data = new Object[1][3]; 
        data[0][0] = "1"; 
        data[0][1] = "User1"; 
        data[0][2] = "Delete"; 
       }else { 
        data = new Object[0][]; 
       } 
       table.setModel(new CustModel(data)); 
      } 
     } 
    } 


    class AddListener extends MouseAdapter{ 

     @Override 
     public void mouseClicked(MouseEvent evnt) { 
      if(table.getModel().getRowCount() == 2) { 
       return; 
      } 
      Object[][] data = new Object[table.getModel().getRowCount() + 1][3]; 
      for(int i = 0; i <= table.getModel().getRowCount(); i++) { 
       data[i][0] = i; 
       data[i][1] = "User" + i; 
       data[i][2] = "Delete"; 
      } 
      table.setModel(new CustModel(data)); 
     } 

    } 

    class CustModel extends AbstractTableModel { 
     private String[] columnNames = {"ID", "NAME", "DELETE"}; 
     private Object[][] data = null; 

     public CustModel(Object[][] data) { 
      this.data = data; 
     } 
     public int getColumnCount() { 
      return columnNames.length; 
     } 

     public int getRowCount() { 
      return data.length; 
     } 

     public String getColumnName(int col) { 
      return columnNames[col]; 
     } 

     public Object getValueAt(int row, int col) { 
      return data[row][col]; 
     } 

     public Class getColumnClass(int col) { 
      return getValueAt(0, col).getClass(); 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("SwapTableModel"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     TestCustTableModel obj = new TestCustTableModel(); 
     obj.display(); 
    } 
} 

此時擺動的objCustTableModel的基礎上,使用objCustTableModel2對象 後第一內部調用getColumnClass功能。我想限制以objCustTableModel爲基礎的呼叫。

+2

發佈一些代碼,而不是描述英文代碼(這我無法到目前爲止理解)。發佈[SSCCE](http://sscce.org)並告訴我們你卡在哪裏。 –

+0

@GuillaumePolet,編輯問題 – Navnath

+0

請whats'覆蓋以下功能顯示按鈕'你想在JTable中顯示JButtons,然後存儲字符串值作爲模型中JButton的描述,真的你想要做什麼.... – mKorbel

回答

4

example開始,我發現getColumnClass()實現沒有意外的行爲,如下所示。

private Model() { 
    final Object[] data = {this.toString()}; 
    this.model = new DefaultTableModel(data, 1){ 

     @Override 
     public Class<?> getColumnClass(int columnIndex) { 
      System.out.println(data[0]); 
      return super.getColumnClass(columnIndex); 
     } 
    }; 
    model.addRow(data); 
} 

注意JTable可以調用getColumnClass()任何時候它確定一個細胞都需要渲染。如有必要,您可以使用EventQueue.invokeLater()安排將在所有待處理事件處理完成後發生的事情。

EventQueue.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     // do something 
    } 
}); 

附錄:

  • 如果getAutoCreateRowSorter()truesetModel()嘗試使用舊模式恢復創造了RowSorter

  • 您可以指定setAutoCreateRowSorter(true)後你改款車型,如下圖所示,或擴展您的TableModel更新替代模型,如圖所示here

  • 使用ActionListener代替JButton代替MouseListener

  • 對於表中的按鈕使用TableCellEditor,如herehere所示。

代碼:

addButton.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (table.getModel().getRowCount() == 2) { 
      return; 
     } 
     Object[][] data = new Object[table.getModel().getRowCount() + 1][5]; 
     table.setRowSorter(null); 
     for (int i = 0; i <= table.getModel().getRowCount(); i++) { 
      data[i][0] = i; 
      data[i][6] = "User" + i; 
      data[i][7] = "Delete"; 
     } 
     table.setModel(new CustModel(data)); 
     table.setAutoCreateRowSorter(true); 
    } 
}); 
+0

您好Trashgod,我檢查了您建議的示例。如果您只是調試相同的示例(查看對象id),您可以看到,在更改下拉值時,setModel()首先從舊對象調用getColumnClass()函數,然後再從新模型對象調用。這就是我的問題。我只想調用'getColumnClass()'函數只對新的模型對象。 – Navnath

+1

@Navnath [你可以hardocde getColumnClass](http://stackoverflow.com/a/6233119/714968) – mKorbel

+0

@mKorbel'getColumnClass()'沒有任何關係。就這一切而言,當我使用'setModel()'函數將新模型設置爲表時,模型類中的函數會被調用兩次。 mKorbel,謝謝你正在關注這個主題,請給我一些建議。 – Navnath

3
DefaultTableModel model ; 
    /** Creates new form DynRowAdd */ 
    public DynRowAdd() { 
     initComponents(); 
      model = new DefaultTableModel(); 
        jTable1.setModel(model); 
        model.addColumn("Id"); 
        model.addColumn("First Name"); 
        model.addColumn("Last Name"); 
        model.addColumn("Company Name"); 
    } 
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           

     model.addRow(new Object[]{jTextField1.getText(), jTextField2.getText(),jTextField3.getText(),jTextField4.getText()}); 

    }     
+1

爲我工作謝謝! – mustangDC